我正在将自定义标记语言转换为TeX.
我有一个这样的文件:
macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}
these are extra lines
another extra line
there can be any number of extra lines
e
macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}
this is extra
this is extra too
e
我需要这样的结果:
macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}{
these are extra lines
another extra line
there can be any number of extra lines
}
macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}{
this is extra
this is extra too
}
请注意,e
本身就在一行上,表示一组数据的末尾,它只是被一个右括号取代。
我可以简单地使用这个:
sed -i 's/^e$/}/g' file.tex
结果是:
macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}
these are extra lines
another extra line
there can be any number of extra lines
}
macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}
this is extra
this is extra too
}
问题是,我还需要一个匹配的起始括号来包围e
之前的额外文本。
一种方法是:
- 替换每次出现的
}
- 但前提是这种情况已经结束
- 并且仅当它是在
e
完全自己出现之前出现的最后一个事件
这是我能想到的最接近的数字,不确定如何在不包含更多}$
:匹配的任何行之间进行匹配
sed -i 's/}$n.*n.*n.*n^e$/}{&}/g' file.tex
如何将最后的额外文本包装在{
和}
中?
使用空RS
使用awk
更容易做到这一点。以下是gnu-awk
解决方案:
awk -v RS= '{sub(/.*}/, "&{"); sub(/ne$/, "n}"); ORS=RT} 1' file
macro{stuff}
{more stuff}
{yet other stuff}
{some stuff}{
these are extra lines
another extra line
there can be any number of extra lines
}
macro{yet more stuff stuff}
{even more stuff}
{yet other stuff}
{some stuff}{
this is extra
this is extra too
}
或者在任何版本的awk
:中
awk -v RS= '{sub(/.*}/, "&{"); sub(/ne$/, "n}n")} 1' file
没有@anubhava的awk
解决方案那么简洁或优雅,但作为练习,我在GNUsed
中实现了相同的解决方案。
sed -n '/^e$/{ z; x; s/.*}/&{/; s/$/n}/; p; d; }; /^$/d; H; ${ H; x; p; }' file
分解-/^e$/{ z; x; s/.*}/&{/; s/$/n}/; p; d; };
通过组件/^e$/{ ... }
在只有e
的行上执行此操作列表:z
是一个清空模式空间的GNU选项x
ex
更改模式和保留空格s/.*}/&{/
在块中最后一个闭合的paren之后添加一个打开的parens/$/n}/
在e
所在的位置添加新行和}
p
将p
打印图案空间,d
将d
删除记录并继续。
/^$/d
删除之间的空记录H
表示H
将模式空间记录旧(追加(到保持空间上,以便我们累积块,直到到达下一个e
终止符行或结束。
${ H; x; p; }
只是确保打印最后一个e
之后的任何记录
如果你不在乎,或者你知道不应该有,就跳过它。
如果你不使用GNUsed
,它看起来会有点不同,哈哈
使用所提供的输入,匹配}
之间的任何内容,直到线路上的e
-带有-z
选项的GNU sed:
sed -Ez 's/([^}]*)ne(n|$)/{1n}2/g'
这是我喜欢使用tac
的地方
tac file | awk '
/^e$/ {print "}"; p=1; next}
p && /^{/ {print $0 "{"; p=0; next}
1
' | tac
该awk命令在第一行添加大括号,从替换e
后的大括号开始。
当我看到诸如";为最后X〃做一些事情;,我认为"反转文件并首先对X执行操作,然后重新反转文件
如果ed
可用/可接受。
脚本script.ed
g?^e$?s/.*/}/
?^{.*?s/$/{/
,p
Q
ed -s file.txt < script.ed
在一行中,引用bash$''
的语法
printf '%sn' $'g?^e$?s/.*/}/\n?^{.*?s/$/{/' ,p Q | ed -s file.txt
这可能对你有用(GNU sed(:
sed 'N;s/}n([^{])/}{n1/;s/ne$/n}/;P;D' file
有两种情况需要替换:
- 当一行以
}
结束,但下一行不以{
开始时 - 当一行仅包含CCD_ 45
通过使用N
、P
和D
命令打开两行窗口,可以满足这两种条件。
第一种方法是将{
附加到窗口的第一行。
第二种方法是将CCD_ 50替换为CCD_。