2016-12-02 104 views
1

我有一个巨大的XML文件,需要更改我知道的行上方出现的几行100行。搜索字符串并替换上面的行中的字符串

<errorCode>4544</errorCode> 
<severity>4</severity> 
<modelDescription>Licensing: Invalid license</modelDescription> 

我希望到grep为“许可:无效的许可证”,改变为“4”,或任何其他号码便可。

我试着这样做:

sed -i '/Invalid license/{n;s/4/6/;}' file 

,但没有奏效。任何建议如何我可以grep的模式,然后改变它上面的值?

+0

请不要使用“巨大”之类的术语。使用数字(我们毕竟是工程师)。这可能会影响答案。 –

回答

1

不要使用SED XML解析,因为它不是设计来处理XML的语法,写在SED的XML解析器是一项艰巨的任务。此外,还有许多有用的工具可以用于此目的。

考虑这个XML:

<root> 
    <item> 
    <errorCode>4000</errorCode> 
    <severity>2</severity> 
    <modelDescription>Some error</modelDescription> 
    </item> 
    <item> 
    <errorCode>4544</errorCode> 
    <severity>4</severity> 
    <modelDescription>Licensing: Invalid license</modelDescription> 
    </item> 
</root> 

您可以轻松地xmlstarlet修改severity值:

xmlstarlet ed -u '//item[severity = 4 
and modelDescription = "Licensing: Invalid license"]/severity' \ 
    -v 100 file.xml 

命令更新(-u)通过更换原值severity元素的值(4 )与100。 XPath表达式为所有item元素选择severity元素,其中severity子值为4modelDescription子值为Licensing: Invalid license的子元素。

结果打印到标准输出。要就地编辑文件,请使用--inplace选项:xmlstarlet ed --inplace -u ...

输出

<?xml version="1.0"?> 
<root> 
    <item> 
    <errorCode>4000</errorCode> 
    <severity>2</severity> 
    <modelDescription>Some error</modelDescription> 
    </item> 
    <item> 
    <errorCode>4544</errorCode> 
    <severity>100</severity> 
    <modelDescription>Licensing: Invalid license</modelDescription> 
    </item> 
</root> 
1

您可以存储上一行并检查当前行是否符合您的模式。如果是这样,修改上一行并打印,否则打印。请看下面:

while IFS= read line 
do 
    echo $line | grep "<severity>[0-9]</severity>" > /dev/null && { 
     sev=$line 
    } || { 
     echo $line | grep "Invalid license" > /dev/null && { 
      echo $sev | sed "s/4/5/" 
     } || { 
      if [ ! -z $sev ]; then echo $sev; fi 
     } 
     sev="" 
     echo $line 
    } 
done < file 
1

这里有一个流XSLT 3.0转换,没有工作,假设您展示被包裹在一个item元素的元素:

<xsl:transform version="3.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<xsl:mode streamable="yes" on-no-match="shallow-copy"/> 
<xsl:mode name="c" streamable="no" on-no-match="shallow-copy"/> 

<xsl:template match="item"> 
    <xsl:apply-templates select="copy-of(.)" mode="c"/> 
</xsl:template> 

<xsl:template mode="c" 
    match="severity[following-sibling::modelDescription= 
        'Licensing: Invalid license']"> 
    <severity>6</severity> 
</xsl:template> 

</xsl:transform> 

元素具有该项目是在处理严重性元素时需要“预见”,并且在流模式下无法完成,因此在处理之前进行复制。