我使用sed来匹配多行。
me@CYGWIN:$ cat foo.txt
Click on <menucascade>
<uicontrol>File</uicontrol>
<uicontrol>Save</uicontrol>
<uicontrol>Options</uicontrol>
<uicontrol>PDF</uicontrol>
</menucascade>.
我想要sed:
如果我知道使用uicontrol的次数,我可以使用N将下一行添加到模式空间:
me@CYGWIN:$ sed '/<menucascade>/{N;N;N;N; s/<uicontrol>\([^<]*\)<\/uicontrol>/<b>\1<\/b>\ >/g}' foo.txt
Click on <menucascade>
<b>File</b> >
<b>Save</b> >
<b>Options</b> >
<b>PDF</b> >
</menucascade>.
但是,如果我不知道使用uicontrol的次数(因此不知道要添加的N的数量),该怎么办?在Cygwin上,sed似乎在5 N之后最大化。因此,如果我高估并且投入超过5个N,它根本不起作用。
me@CYGWIN:$ sed '/<menucascade>/{N;N;N;N;N;N; s/<uicontrol>\([^<]*\)<\/uicontrol>/<b>\1<\/b>\ >/g}' foo.txt
Click on <menucascade>
<uicontrol>File</uicontrol>
<uicontrol>Save</uicontrol>
<uicontrol>Options</uicontrol>
<uicontrol>PDF</uicontrol>
</menucascade>.
首先:任何人都可以解释为什么sed脚本无法与6个N匹配?
第二:任何人都可以建议如何使用sed在menucascade中匹配n个uicontrol实例?或者,如果sed是错误的工具,任何人都可以建议一个在bash脚本中工作的替代方法吗?
感谢。
答案 0 :(得分:0)
您可以根据需要多次使用N
,但是(来自POSIX):
如果没有下一行输入可用,则N命令动词应分支到脚本的末尾
因此,如果只是不小心使用它们,最终它们会导致你的脚本结束。
POSIX也不保证模式空间中超过8192个字节,但你可能正在使用支持更多方式的GNU sed。
正确的方法是使用像xmlstarlet
这样的xml工具,虽然这假设你至少使用了xhtml的外观:
$ cat foo.xml
<html>
<h1>Blah</h1>
<p>
Click on <menucascade>
<uicontrol>File</uicontrol>
<uicontrol>Save</uicontrol>
<uicontrol>Options</uicontrol>
<uicontrol>PDF</uicontrol>
</menucascade>
</p>
<p>
<uicontrol>Other stuff</uicontrol>
</p>
</html>
然后
$ xmlstarlet ed -r "//menucascade/uicontrol" -v b foo.xml
<?xml version="1.0"?>
<html>
<h1>Blah</h1>
<p>
Click on <menucascade><b>File</b><b>Save</b><b>Options</b><b>PDF</b></menucascade>
</p>
<p>
<uicontrol>Other stuff</uicontrol>
</p>
</html>