sed正则表达式不匹配

时间:2013-04-04 17:56:17

标签: xml regex bash sed

我有一个XML文件,如下所示:

<Group>
    <Name>Awesome Group</Name>
    <Notes />
    <Date>2013-04-04</Date>
    <Expires>False</Expires>
    <Icon>7</Icon>
    <Tags />
</Group>

我正尝试使用此命令在<Notes /></Icon>之间打印所有内容:

$ sed -n '/\<Notes \/\>/ p' file.xml

注意我在关闭括号之前转出了开括号和闭括号以及正斜杠。这不会返回任何匹配,我觉得很奇怪。

更奇怪的是这个命令有效:

$ sed -n '/<Notes \/>/ p' file.xml

为什么这个命令有效,因为我没有转出开括号和近括号?

修改

ruakh有帮助地指出sed有不同的实现,并且开放和关闭括号不需要被转义(我认为sed使用Perl语法来表示正则表达式)。我在Unix&amp;上发现了另一篇文章Linux也很有帮助:https://unix.stackexchange.com/questions/32907/what-characters-do-i-need-to-escape-when-using-sed-in-a-sh-script

现在我遇到了匹配多行正则表达式的问题。为什么这不起作用?

$ sed -n -r '/^<Notes \/>[\S\s]*?<\/Icon>$/ p' file.xml

我尝试过使用-r(扩展模式),使用^$,使用.*代替[\S\s]*。 ,都没有比赛

2 个答案:

答案 0 :(得分:3)

在sed中,<>没有特殊含义,但\<\>有时:在某些实现中,它们意味着&#34;单词的开头&#34;和#34;词尾#34;例如,这个Bash命令:

{ echo a ; echo ba ; echo b a ; } | sed -n '/\<a/ p'
在某些系统上,

会打印ab a(在一个单词的开头有a),但不是ba (没有&#39; t。)。

(从你选择的标签来看,你可能习惯了Perl?Perl做出了一个面向未来的保证\,当它在非单词字符之前时,总是会逃脱它。例如,<没有特殊含义,但\<无论如何都保证<。但并非所有正则表达式引擎都采用这种方法。)


编辑问题的

编辑

Sed一次处理一行 - 这是使其成为&#34;流编辑器的一部分&#34; - 所以多线正则表达式基本上注定要失败。但是,在您的情况下,您实际上并不需要多行正则表达式;您只想查找包含<Notes />的行和包含</Icon>的(不同)行,并打印两者之间的所有行(包括)。为此,您可以使用地址范围,指定/<Notes \/>/的起始地址和/<\/Icon>/的结束地址:

sed -n '/<Notes \/>/,/<\/Icon>/ p'

(见§3.2 "Selecting lines with sed" in the GNU sed user's manual.。)

答案 1 :(得分:1)

sed是一个很好的工具,可以在一行上进行简单的替换,对于你应该使用awk的任何其他文本操作。这是一个GNU awk解决方案:

$ gawk -v RS='\0' '{print gensub(/.*(<Notes \/>.*<\/Icon>).*/,"\\1","")}' file
<Notes />
    <Date>2013-04-04</Date>
    <Expires>False</Expires>
    <Icon>7</Icon>

请注意,上面只是在您要求的符号之间打印,而不是符号出现的整行。