2010-04-01 68 views
18

我有一個xml文件,我想使用bash腳本進行配置。例如,如果我有這樣的XML:使用bash腳本添加/刪除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>標籤之間的所有文本

我還需要編寫一個腳本來添加刪除的部分。

+2

我會建議不要使用bash/SED/AWK /等。對於這類事情,建議使用Python,Ruby或Perl。 – 2010-04-01 16:36:37

回答

22

這在sed中不會很難做到,因爲sed也適用於範圍。

試試這個(假設XML是在一個名爲foo.xml文件):

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

-i會寫換入原始文件(使用-i。李明博保持原)

備份副本,這sed命令將在所有由指定範圍內的

# all of the lines between a line that matches <b> 
# and the next line that matches <\/b>, inclusive 
/<b>/,/<\/b>/ 

所以行執行操作d(刪除),用簡單的英語,這個命令會刪除所有之間和包括<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 
+4

如果在同一行上前面的''沒有任何重要性,並且在同一行上的''後面沒有重要性, t一般適用於XML,但可能適用於提問者的特殊情況。 – Arkku 2010-04-01 18:45:03

+0

如果在之前或之前在行上有重要內容,塊註釋(替換

+0

這種考慮增加了我對XML對配置文件的矯枉過正的認知;) – a1an 2012-09-06 15:34:53

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

@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> 
+0

Thx幫助我:D – Chris 2012-06-07 07:30:36

14

使用xmlstarlet:

#xmlstarlet ed -d "https://stackoverflow.com/a/b" file.xml > tmp.xml 
xmlstarlet ed -d "//b" file.xml > tmp.xml 
mv tmp.xml file.xml 
+0

可能應該做的正確,並添加一個條件(如果操作成功,只對原始文件進行重命名)。爲了做得更好,也可以使用'mktemp'來生成一個保證非衝突名稱的臨時文件,這也可以避免一些與使用常量臨時文件名有關的安全攻擊的副作用。 – 2015-03-24 16:18:52

+1

儘管有這些警告,但這仍然比使用'sed'好得多。 – 2015-03-24 16:20:07

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

在ubuntu 9.x版本上使用默認存儲庫apt-get install xmlstarlet 。 未在文檔中找到-L標誌。 是在Ubuntu 10.0.4嗎? – user77115 2011-07-28 15:31:00