使用bash脚本添加/删除xml标记

时间:2010-04-01 16:27:45

标签: xml bash scripting

我有一个我想用bash脚本配置的xml文件。例如,如果我有这个xml:

<a>

  <b>
    <bb>
        <yyy>
            Bla 
        </yyy>
    </bb>
  </b>

  <c>
    <cc>
      Something
    </cc>
  </c>

  <d>
    bla
  </d>
</a>

(已删除机密信息)

我想编写一个bash脚本,它将删除<b>部分(或注释它),但保持xml的其余部分不变。我是整个脚本的新东西。我想知道是否有人能给我一个关于我应该注意什么的提示。

我原以为sed可以用除了 sed是一个行编辑器。我认为删除<b>代码很容易,但我不确定sed是否能够删除 <b>代码之间的所有文字

我还需要编写一个脚本来添加已删除的部分。

7 个答案:

答案 0 :(得分:23)

这在sed中并不难做到,因为sed也适用于范围。

试试这个(假设xml位于名为foo.xml的文件中):

sed -i '/<b>/,/<\/b>/d' foo.xml

-i会将更改写入原始文件(使用-i.bak保留原始文件的备份副本)

此sed命令将对范围

指定的所有行执行操作d(删除)
# all of the lines between a line that matches <b>
# and the next line that matches <\/b>, inclusive
/<b>/,/<\/b>/

因此,用简单的英语,这个命令将删除&lt; b&gt;之前的行之间的所有行。和&lt; / b&gt;

的行

如果你想注释掉这些线条,请尝试以下方法之一:

# block comment
sed -i 's/<b>/<!-- <b>/; s/<\/b>/<\/b> -->/' foo.xml

# comment out every line in the range
sed -i '/<b>/,/<\/b>/s/.*/<!-- & -->/' foo.xml

答案 1 :(得分:14)

使用xmlstarlet:

#xmlstarlet ed -d "/a/b" file.xml > tmp.xml
xmlstarlet ed -d "//b" file.xml > tmp.xml
mv tmp.xml file.xml

答案 2 :(得分:9)

您可以使用此类XSLT,这是一种经过修改的身份转换。它默认复制所有内容,并且b的空模板不执行任何操作(从输出中有效删除):

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<!--Identity transform copies all items by default -->
<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<!--Empty template to match on b elements and prevent it from being copied to output -->
<xsl:template match="b"/>

</xsl:stylesheet>

创建一个执行变换using Java and the Xalan commandline utility的bash脚本,如下所示:

  

java org.apache.xalan.xslt.Process -IN   foo.xml -XSL foo.xsl -OUT foo.out

结果如下:

<?xml version="1.0" encoding="UTF-16"?><a><c><cc>
      Something
    </cc></c><d>
    bla
  </d></a>

编辑:如果您希望将b注释掉,以便更容易放回,请使用此样式表:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

    <!--Identity transform copies all items by default -->
    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!--Match on b element, wrap in a comment and construct text representing XML structure by applying templates in "comment" mode -->
    <xsl:template match="b">
        <xsl:comment>
            <xsl:apply-templates select="self::*" mode="comment" />
        </xsl:comment>
    </xsl:template>

    <xsl:template match="*" mode="comment">
        <xsl:value-of select="'&lt;'"/>
            <xsl:value-of select="name()"/>
        <xsl:value-of select="'&gt;'"/>
            <xsl:apply-templates select="@*|node()" mode="comment" />
        <xsl:value-of select="'&lt;/'"/>
            <xsl:value-of select="name()"/>
        <xsl:value-of select="'&gt;'"/>
    </xsl:template>

    <xsl:template match="text()" mode="comment">
        <xsl:value-of select="."/>
    </xsl:template>

    <xsl:template match="@*" mode="comment">
        <xsl:value-of select="name()"/>
        <xsl:text>="</xsl:text>
        <xsl:value-of select="."/>
        <xsl:text>" </xsl:text>
    </xsl:template>

</xsl:stylesheet>

它产生这个输出:

<?xml version="1.0" encoding="UTF-16"?><a><!--<b><bb><yyy>
            Bla
        </yyy></bb></b>--><c><cc>
      Something
    </cc></c><d>
    bla
  </d></a>

答案 3 :(得分:6)

如果您想要最适合替换sed的XML数据,那么它将是一个XSLT处理器。与sed一样,它是一种复杂的语言,但专门用于XML到任何转换的任务。

另一方面,这个确实似乎是我认真考虑切换到真正的编程语言的地方,比如Python。

答案 4 :(得分:3)

@OP,你可以使用awk例如

$ cat file
<a>                              

some text before   <b>
    <bb>
        <yyy>
            Bla
        </yyy>
    </bb>
  </b> some text after

  <c>
    <cc>
      Something
    </cc>
  </c>

  <d>
    bla
  </d>
</a>

$ awk 'BEGIN{RS="</b>"}/<b>/{gsub(/<b>.*/,"")}1' file
<a>

some text before
 some text after

  <c>
    <cc>
      Something
    </cc>
  </c>

  <d>
    bla
  </d>
</a>

答案 5 :(得分:3)

# edit file inplace
xmlstarlet ed -L -d "//b" file.xml

答案 6 :(得分:0)

sed -i '/<b>/,/<\/b>/d' foo.xml

如果b标签也定义了一个值,那么这项工作会起作用 在大约HTML中,b标签以<b id="Test Step">

开头