2016-12-02 7 views
1

Ich habe eine gigantische XML-Datei und muss ein paar 100 Zeilen ändern, die oberhalb einer Zeile, die ich kenne, auftreten.Suche nach einem String und ersetze String in der obigen Zeile

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

Ich möchte für „Lizenzierung: Ungültige Lizenz“ grep und ändern Sie die „4“ darüber oder jede andere Zahl.

Im Versuch, wie etwas zu tun:

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

aber es hat nicht funktioniert. Irgendwelche Vorschläge, wie ich nach einem Muster grep und dann einen Wert darüber ändern kann?

+0

Bitte verwenden Sie keine Begriffe wie "gigantisch". Verwenden Sie Zahlen (wir sind schließlich Ingenieure). Es könnte die Antwort gut beeinflussen. –

Antwort

1

Sie SED nicht für das Parsen von XML verwenden, da es nicht ausgelegt ist, XML-Syntax zu handhaben, und in SED einen XML-Parser zu schreiben ist eine schwierige Aufgabe. Außerdem gibt es viele nützliche Tools genau für diesen Zweck.

Betrachten Sie diese 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> 

Sie können ganz einfach ändern Sie den severity Wert mit xmlstarlet:

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

Der Befehl Updates (-u) den Wert von severity Element durch den ursprünglichen Wert ersetzt (4) mit 100. Der XPath-Ausdruck wählt severity Elemente für alle item Elemente mit severity Kind mit Wert 4 und modelDescription Kind mit Wert Licensing: Invalid license.

Das Ergebnis wird auf die Standardausgabe gedruckt. Um die Datei direkt zu bearbeiten, verwenden Sie --inplace Option: xmlstarlet ed --inplace -u ....

Ausgabe

<?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

Sie können die vorherige Zeile speichern und die aktuelle Zeile prüfen, wenn sie mit Ihrem Muster übereinstimmt. Wenn ja, ändern Sie die vorherige Zeile und drucken Sie, andernfalls drucken Sie als solche. Bitte beachten Sie die folgenden:

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

Hier ist ein Streaming-XSLT 3.0 Transformation, die die Arbeit macht, vorausgesetzt, die Elemente, die Sie zeigen, sind in einem Artikel Element gewickelt:

<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> 

Der Artikel Elemente sein müssen kopiert, bevor Sie verarbeitet werden, weil Sie bei der Verarbeitung des Schweregradelements "vorausschauen" möchten, was im Streaming-Modus nicht möglich ist.

Verwandte Themen