SED über mehrere Leitungen ersetzen


10

Ich versuche diese drei Zeilen zu finden:

<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->

und ersetzen Sie sie durch:

<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />

Wenn ich es versuche

sudo sed -i 's:<!-- <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" /> -->:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />:' /myfile.xml

Es findet es nicht, ich habe auch versucht, es einzufügen, aber es hat immer noch nicht funktioniert:

sudo sed -i 's:<!--\n <Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />\n -->:<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />:' /myfile.xml

Diese werfen keine Fehler, sie kommentieren die Zeile einfach nicht aus. Jeder Rat würde helfen, danke!

Antworten:


6

sed liest jede Zeile nacheinander, sodass sie niemals mit einem mehrzeiligen Muster übereinstimmt, es sei denn, Sie bewegen sie in die richtige Richtung. Der NBefehl liest eine Zeile aus der Eingabe und hängt sie an den Musterbereich an.

sed -i -e '/^<!--$/ {
    N; /\n<Connector port="8009" protocol="AJP\/1\.3" redirectPort="8443" \/>$/ {
        N; /\n-->$/ {
            s/^<!--\n//; s/\n-->$//
        }
    }
}' /myfile.xml

Wenn Sie einen anderen Befehl als benötigen s, sollten Sie wahrscheinlich von sed zu awk oder perl wechseln. Hier ist ein etwas flexibleres Perl-Snippet, das allgemeiner mit mehrzeiligen Kommentaren umgeht.

perl -i -pe '
    if (/<!--/) { $_ .= <> while !/-->/;
        s[<!--\n(<Connector port="8009" protocol="AJP/1\.3" redirectPort="8443" />)\n-->][$1];
    }' /myfile.xml

6

Sed arbeitet zeilenweise. Es kann für mehrere Zeilen verwendet werden, aber es wurde nicht so entworfen - und meiner Meinung nach zeigt es definitiv, wenn Sie versuchen, es so zu verwenden. Wenn Sie sich jedoch für diesen Weg entscheiden, müssen Sie wahrscheinlich Register verwenden. Überprüfen Sie einige der Lösungen unter /programming/1251999/sed-how-can-i-replace-a-newline-n, um zu sehen, wie dies durchgeführt werden kann.

Ich bevorzuge es, Perl anstelle von Sed für diese Art von Aufgabe zu verwenden (mehrzeilig, meine ich). Das Boilerplate, das Sie vor dem Suchen und Ersetzen ( BEGIN...) hinzufügen müssen, ist nicht offensichtlich, aber der reguläre Ausdruck scheint mir sauberer zu sein:

perl -i.bak -pe 'BEGIN{undef $/;} s/<!--string-->/string/smg' file.xml

Oder verwenden Sie die Gruppierung, um den Ausdruck zu verkürzen und Ihnen zu ermöglichen, dort einen regulären Ausdruck zu verwenden:

perl -i.bak -pe 'BEGIN{undef $/;} s/<!--(string_or_regex)-->/\1/smg' file.xml

Es sollte sowohl bei Vorkommen mit als auch ohne Zeilenumbrüche zwischen den Kommentarmarkierungen und dem zu kommentierenden Code funktionieren.

Adaptiert von:

/programming/1030787/multiline-search-replace-with-perl


Vielen Dank für Ihre Hilfe, sieht aus wie es ein Schmerz ist, ich entschied mich für eine Problemumgehung
Doug Molineux


1
  • /<\!--/ : passende Zeichenfolge
  • :X : Dies ist eine Bezeichnung für den Verzweigungsbefehl "b"
  • /-->/ : passende Zeichenfolge
  • s@...@...@p : Streifen "<! -", "->" und Druckergebnis
  • d : Musterraum löschen und neuen Zyklus starten
  • N : Wenn nicht mit / -> / übereinstimmen, fügen Sie eine Zeile hinzu
  • bX : verzweige zu: X-Label
  • p : Drucke einfach eine Zeichenfolge, die nicht mit / <! - / übereinstimmt

sed -rn '
/<!--/ {
    :X
    /-->/ {
        s@<!--\s*(<.+/>)\s*-->@\1@p
        d
    }
    N
    bX
};p'

und diese zweite Methode ist eine einfache wörtliche Ersetzung durch Kopieren und Einfügen für übliche kleine Textdateien (benötigt eine Shell-Skriptdatei)

#!/bin/bash

# copy & paste content that you want to substitute

AA=$( cat <<\EOF | sed -z -e 's#\([][^$*\.#]\)#\\\1#g' -e 's#\n#\\n#g'
<!--
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
-->
EOF
)

BB=$( cat <<\EOF | sed -z -e 's#\([&\#]\)#\\\1#g' -e 's#\n#\\n#g'
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
EOF
)

sed -z -i 's#'"${AA}"'#'"${BB}"'#g' *.xml   # apply to all *.xml files

1) Vielen Dank für Ihre Antwort. 2) Das Einfügen nur von Codefragmenten ist nicht wirklich in Ordnung. Es wäre viel besser, wenn Sie erklären würden, was es tut und wie.
Peterh - Wiedereinsetzung Monica
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.