我有一个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]*
。 ,都没有比赛
答案 0 :(得分:3)
在sed中,<
和>
没有特殊含义,但\<
和\>
有时做:在某些实现中,它们意味着&#34;单词的开头&#34;和#34;词尾#34;例如,这个Bash命令:
{ echo a ; echo ba ; echo b a ; } | sed -n '/\<a/ p'
在某些系统上,会打印a
和b 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>
请注意,上面只是在您要求的符号之间打印,而不是符号出现的整行。