2014-07-16 166 views
0

我嘗試用sed替換XML文件中的字符串,但由於其正則表達式不支持非貪婪表達式,所以遇到問題。替換XML文件中的字符串

XML實例:

<opt> 
    <Node active="yes" file="/home/user/random_filename" last_time="17/07/14-00:02:07" time_in_min="5" /> 
</opt> 

我要查找的文件屬性,它是隨機字符串,並用另一個字符串替換它。

該命令替換字符串,但刪除尾隨數據。

sed 's/file=".*"/file="new_file_name"/' file.xml 

輸出:

<opt> 
    <Node active="yes" file="new_file_name" /> 
</opt> 

我應該如何處理呢?

+0

[regex match non greedy]的可能重複(http://stackoverflow.com/questions/11898998 /正則表達式匹配非貪婪) – whereswalden

回答

2

使用"[^"]*",而不是".*"

輸入:

<opt> 
    <Node active="yes" file="/home/user/random_filename" last_time="17/07/14-00:02:07" time_in_min="5" /> 
</opt> 

命令:

sed 's/file="[^"]*"/file="new_file_name"/' 

輸出:

<opt> 
    <Node active="yes" file="new_file_name" last_time="17/07/14-00:02:07" time_in_min="5" /> 
</opt> 
1

這不使用sed但是在處理xml文檔時,您可能需要考慮xslt。它可能是您解決問題的最佳解決方案,但它非常適合使用xml。

filter.xsl:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" version="1.0" omit-xml-declaration="yes"/> 

<!-- The replacement string is passed as a parameter. 
    You can have as many param elements as you need. --> 
<xsl:param name="NEW_NAME"/> 

<!-- Copy all attributes and nodes... --> 
<xsl:template match="@*|node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@*|node()"/> 
    </xsl:copy> 
</xsl:template> 

<!-- ...but when you encounter an element with a file attribute, 
    replace it with the value passed in the parameter named $NEW_NAME. --> 
<xsl:template match="@file"> 
    <xsl:attribute name="file"> 
     <xsl:value-of select="$NEW_NAME"/> 
    </xsl:attribute> 
</xsl:template> 

</xsl:stylesheet> 

一個例子的libxslt(補充一點,你需要儘可能多的--stringparam名稱/值對):

xsltproc --stringparam NEW_NAME new_file_name filter.xsl file.xml 

結果:

<opt> 
    <Node active="yes" file="new_file_name" last_time="17/07/14-00:02:07" time_in_min="5"/> 
</opt> 
+0

不錯!我會考慮它。我需要改變多個參數,它看起來像最方便的方式。謝謝。 – Alex

+0

如果需要,匹配屬性xpath表達式可以變得更具體。例如,要僅更改Node元素中的文件屬性,請將'match =「@ file」'更改爲'match =「Node/@ file」'。您還可以根據文件屬性的內容進行匹配。要僅更改以'/ home/user /'開頭的那些,請使用'match ='節點/ @文件[開始於(。,'/ home/user /')]「'。 –

0
$ sed 's/\(.*file="\)[^"]*/\1new_file_name/' file 
<opt> 
    <Node active="yes" file="new_file_name" last_time="17/07/14-00:02:07" time_in_min="5" /> 
</opt>