web-dev-qa-db-ja.com

bashスクリプトを使用してxmlタグを追加/削除する

Bashスクリプトを使用して構成するxmlファイルがあります。たとえば、このxmlがある場合:

<a>

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

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

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

(機密情報は削除されました)

セクション<b>を削除する(またはコメントを付ける)が、残りのxmlはそのままにしておくbashスクリプトを記述したいと思います。私はスクリプト作成全体についてかなり新しいです。何を調べればよいのか、誰かがヒントをくれないかと思っていました。

Sedはexceptを使用できると考えていました。sedはラインエディタです。 <b>タグを削除するのは簡単だと思いますが、sedがすべてのテキストbetween<b>タグを削除できるかどうかはわかりません。

削除したセクションを元に戻すためのスクリプトも作成する必要があります。

21

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>/

したがって、平易な英語では、このコマンドは<b>を含む行と</ b>を含む行の間の行をすべて削除します

行をコメントアウトする場合は、次のいずれかを試してください。

# 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
25
amertune

Xmlstarletの使用:

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

変更されたID変換であるこのような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>

次のように、変換を実行するbashスクリプトを作成します JavaおよびXalanコマンドラインユーティリティ を使用):

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>

EDIT: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>
9
Mads Hansen

XMLデータのsedの最も適切な置き換えが必要な場合は、XSLTプロセッサになります。 sedと同様に、それは複雑な言語ですが、XMLから何かへの変換のタスクに特化しています。

一方、このdoesは、Pythonなどの実際のプログラミング言語への切り替えを真剣に検討するポイントと思われます。

6
Teddy
# edit file inplace
xmlstarlet ed -L -d "//b" file.xml
3
notmp

@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>
3
ghostdog74