2014-07-16 134 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>