Problem mit Perl Multiline Matching
Ich versuche, ein perl-one-liner zu aktualisieren, einige code, der sich über mehrere Zeilen und Bemerke ein seltsames Verhalten. Hier ist eine einfache text-Datei, die zeigt, dass das problem ich bin zu sehen:
ABCD START
STOP EFGH
Erwartete ich, dass das folgende zu funktionieren, aber es landet nicht ersetzen nichts:
perl -pi -e 's/START\s+STOP/REPLACE/s' input.txt
Nach etwas Experimentieren, fand ich, dass die \s+
im ursprünglichen regex wird mit dem Zeilenumbruch, aber nicht jeder der whitespace auf der 2. Zeile und das hinzufügen einer zweiten \s+
funktioniert auch nicht. So jetzt mache ich den folgenden workaround, das ist das hinzufügen einer intermediate-regex, die nur entfernt die newline:
perl -pi -e 's/START\s+/START/s' input.txt
Dies schafft die folgende temporäre Datei:
ABCD START STOP EFGH
Dann kann ich die original-regex (obwohl die /s
wird nicht mehr benötigt):
perl -pi -e 's/START\s+STOP/REPLACE/s' input.txt
Dadurch entsteht die endgültige, gewünschte Datei:
ABCD REPLACE EFGH
Scheint es, wie der Zwischenschritt nicht notwendig sein sollte. Bin ich etwas fehlt?
/s
wirkt sich nur auf das, was .
entspricht, so daß keiner deiner /s
s benötigt werden InformationsquelleAutor der Frage faman | 2011-05-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
perl -p
Prozesse die Datei eine Zeile zu einem Zeitpunkt. Die regex, die Sie haben ist korrekt, aber es ist nie abgestimmt gegen die multi-line string.Einer einfachen Strategie, vorausgesetzt, die Datei wird in den Speicher passt, ist um das ganze zu Lesen (tun Sie das, ohne
-p
):Hinweis, ich habe die
/g
Modifizierer angeben, globalen Austausch.Als Abkürzung für alle, die extra boilerplate, können Sie das vorhandene Skript mit den
-0777
option:perl -0777pi -e 's/START\s+STOP/REPLACE/sg'
. Hinzufügen/g
ist immer noch notwendig, wenn Sie brauchen, um mehrere Ersetzungen in der Datei.Einen Schluckauf, die auftreten können, wenn auch nicht mit diesem regex: wenn die regex wurden
START.+STOP
, und eine Datei enthält mehrere START - /STOPP-Paaren, die gierige Suche der.+
Essen alles vom ersten START bis zur letzten HALTESTELLE. Können Sie nicht-gierigem matching (match so wenig wie möglich) mit.+?
.Wenn Sie möchten, verwenden Sie die
^
und$
Anker für Zeile Grenzen überall in der Zeichenfolge, dann müssen Sie auch die/m
regex-Modifizierer.InformationsquelleAutor der Antwort Andy
Sie in der Nähe waren. Sie müssen entweder
-00
oder-0777
:InformationsquelleAutor der Antwort tchrist
Relativ einfache one-liner (Lesen der Datei im Speicher):
Einer anderen alternative (nicht so einfach), nicht das Lesen der Datei im Speicher:
InformationsquelleAutor der Antwort sailprog
Hier ist ein one-liner, die nicht Lesen Sie die gesamte Datei in den Speicher, auf einmal:
InformationsquelleAutor der Antwort Sean
InformationsquelleAutor der Antwort jm666