2013-10-07 42 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