2016-12-02 105 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> 

元素具有該項目是在處理嚴重性元素時需要「預見」,並且在流模式下無法完成,因此在處理之前進行復制。