2013-04-04 212 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