2013-10-07 41 views
1

我想使用正則表達式(awk,sed,grep ...)刪除bash中的XML註釋我已經看過其他關於此的問題,但他們錯過了一些東西。這裏是我的XML代碼使用正則表達式在bash中刪除XML註釋

<Table> 
    <!-- 
    to be removed bla bla bla bla bla bl............ 

    removeee 

    to be removeddddd 
    --> 

<row> 
     <column name="example" value="1" ></column> 
    </row> 
</Table> 

所以我比較2個的XML文件,但我不想比較要考慮到的意見。我這樣做

diff file1.xml file2.xml | sed '/<!--/,/-->/d' 

但這隻會刪除以<!--開頭的行和最後一行。它不會刪除之間的所有線。

+0

[不要使用正則表達式來解析xml](http://www.codinghorror.com/blog/2009/11/parsing-html-the-cthulhu-way.html)。使用專門分析xml的工具。你可以使用'tidy'或寫一個身份xslt。 – kojiro

+0

[stripout comments from xml]的可能重複(http://stackoverflow.com/questions/1464697/stripout-comments-from-xml) – kojiro

+0

@kojiro No sir。這個問題的答案使用'tidy'。請閱讀我對@glennjackman的評論回答 – Masster

回答

5

最後,你將不得不向你的客戶/朋友/老師推薦他們需要安裝某種XML處理器。 xmlstarlet是一個很好的命令行工具,但是可以爲任何標準Unix編譯的XSLT實現的編號(或者至少有一些編號大於2),在大多數情況下也適用於Windows。使用基於正則表達式的工具你實在無法做很多XML處理,而且你做的任何事情都很難閱讀,難以維護,並且可能會在特殊情況下失敗,有時會帶來災難性後果。

我沒有花大量時間打磨或審查下面的小awk程序。我認爲它會從兼容的XML文檔中刪除評論。請注意,下面的評論是不符合

<!-- XML comments cannot include -- so this comment is illegal --> 

,它不會被我的腳本正確對待。

下面也是非法的,但因爲我已經在野外看到它,它是不是很難對付,我這樣做:

<!-------------- This comment is ill-formed but... --------------> 

這。沒有保證。我知道這很難閱讀,我不想維護它。它可能會在任意角落的情況下失敗。

awk 'in_comment&&/-->/{sub(/([^-]|-[^-])*--+>/,"");in_comment=0} 
    in_comment{next} 
    {gsub(/<!--+([^-]|-[^-])*--+>/,""); 
     in_comment=sub(/<!--+.*/,""); 
     print}' 
+1

+1但是,你可以請切斷嗎? – kojiro

2
xmlstarlet ed -d '//comment()' file.xml 
+0

謝謝。但我正在爲某人開發這個腳本,他將在不同的linux甚至solaris上運行它。所以,並不是所有的linux都有'xmlstarlet'。我主要關心的是用正​​則表達式來做呢? – Masster

0

你可以用一對 'Perl的xmllint' 得到這份工作做到:(!在我們的例子< - )

cat yourFile.xml | perl -e 'while (<>) { next if (/Start.*End/);if (/Start/) { while (<>) {last if (/End/) }}else {print "$_"; }} ' | xmllint --format - 

用啓動=你開始註釋 結束=你的結局評論(在我們的情況 - >)

我試圖使用grep -vP沒有任何好的結果,因爲我沒有找到如何告訴grep將點理解爲新行(s修飾符)。

2

中最簡單的解決方案,從一個文本文件中刪除所有意見,我能想出是:

sed 's/<!--/\x0<!--/g;s/-->/-->\x0/g' | grep -zv '^<!--' | tr -d '\0' 

爲了解釋:

sed將投入一個null字符是這樣的:

<Table> 
    \0<!-- 
    to be removed bla bla bla bla bla bl............ 

    removeee 

    to be removeddddd 
    -->\0 

<row> 
     <column name="example" value="1" ></column> 
    </row> 
</Table> 

grep -z將該字符視爲「行分隔符」並刪除中間部分,最後tr -d將再次刪除\0

在這種情況下

應該比較如之前被應用到這兩個文件:

diff <(sed 's/<!--/\x0<!--/g;s/-->/-->\x0/g' file1.xml | grep -zv '^<!--' | tr -d '\0') <(sed 's/<!--/\x0<!--/g;s/-->/-->\x0/g' file2.xml | grep -zv '^<!--' | tr -d '\0') 

或更具可讀性與功能:

stripcomments() {sed 's/<!--/\x0<!--/g;s/-->/-->\x0/g' | grep -zv '^<!--' | tr -d '\0'} 

diff <(cat file1.xml | stripcomments) <(cat file1.xml | stripcomments) 

有一些問題與CDATA塊,因爲他們可以被用來具有不平衡的註釋,並且它們具有重要的空字符的可能性較高。 但對於大多數有效的XML文件,這應該工作。

+1

這對於你想要做的大多數事情來說已經足夠了。 – sjas