2013-04-04 154 views
0

我有一个看起来像这样的XML文件:SED正则表达式不匹配

<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上发现了另一篇文章& 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]*,所有没有匹配

回答

3

在SED,<>有没有特别的意义,但\<\>有时:在一些实现中,它们是指“词的开始”和“词的结尾”。例如,这个bash命令:

{ echo a ; echo ba ; echo b a ; } | sed -n '/\<a/ p' 

会,在某些系统中,打印ab a(其中有一个a在词的最开始),但不ba(那里没有)。 (从你选择的标签判断,你可能习惯于Perl?)Perl做出了未来保证,当它位于非单词字符之前时,它总是会逃避它。例如,<已经没有特殊含义,但\<保证是表示<反正但并非所有的正则表达式引擎采用此方法)


编辑用于编辑的问题:。

桑达同时处理一行这是什么使它成为“流编辑器”—的一部分,所以多行正则表达式实际上注定要失败。然而,就你而言,你并不需要多行的正则表达式;您只想找到包含<Notes />的行和包含</Icon>的(不同)行,并打印两个(含)之间的所有行。对于这一点,你可以用一个地址范围,指定的/<Notes \/>/起始地址和/<\/Icon>/最终地址:(见§3.2 "Selecting lines with sed" in the GNU sed user's manual.

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

+0

我以为sed是基于Perl的。谢谢你清理那个。 – 2013-04-04 18:04:52

+0

我知道我可以使用一个范围,但我认为必须有一种方法来在sed中执行多行正则表达式。但是,这很有效。谢谢。 – 2013-04-04 18:52:11

+0

@ davidkennedy85:实际上,sed早于perl,并且perl意图作为更普遍的sed替代品(参见[原始公告](http://groups.google.com/group/comp.sources .unix /树/ browse_frm /月/ 1988年至1902年?_done =%2Fgroup%2Fcomp.sources.unix%2Fbrowse_frm%2Fmonth%2F1988-02%3F&))。 – 2013-04-04 20:29:43

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> 

注意的是,以上只是你要的,而不是整个线路的符号出现在符号之间打印。

+0

很高兴知道。谢谢! – 2013-04-04 22:08:48