
Ich habe eine große Datei, die Sonderzeichen enthält. Darin befindet sich ein mehrzeiliger Code, den ich durch ersetzen möchte sed
.
Das:
text = "\
------ ------\n\n\
This message was automatically generated by email software\n\
The delivery of your message has not been affected.\n\n\
------ ------\n\n"
Muss sich in Folgendes verwandeln:
text = ""
Ich habe den folgenden Code ausprobiert, aber ohne Erfolg:
sed -i '/ text = "*/ {N; s/ text = .*affected.\./ text = ""/g}' /etc/exim.conf
Es ersetzt nichts und zeigt keine Fehlermeldungen an
Ich habe damit herumgespielt, aber nichts, was ich versuche, funktioniert.
Antwort1
Perl zur Rettung:
perl -i~ -0777 -pe 's/text = "[^"]+"/text = ""/g' input-file
-i~
bearbeitet die Datei "an Ort und Stelle" und hinterlässt eine Sicherungskopie-0777
liest die gesamte Datei auf einmal, nicht Zeile für Zeile
Die Ersetzung s///
funktioniert ähnlich wie in sed (d. h. sie gleicht alles ab text = "
, gefolgt von allem außer doppelten Anführungszeichen, und zwar viele Male bis hin zu einem doppelten Anführungszeichen), in diesem Fall funktioniert sie jedoch auf die gesamte Datei.
Antwort2
Sie müssen den Musterraum überprüfen und weiterhin die N
ext-Zeile einfügen, wenn sie nicht übereinstimmt, z. B.
sed '/text = "/{ # if line matches text = "
:b # label b
$!N # pull in the next line (if not the last one)
/"$/!bb # if pattern space doesn't end with " go to label b
s/".*"/""/ # else remove everything between the quotes
}' infile
mit gnu sed
kannst du es schreiben als
sed '/text = "/{:b;$!N;/"$/!bb;s/".*"/""/}' infile
Das ist allerdings nicht sehr effizient. Besser ist es, einfach den Bereich auszuwählen /text = "/,/"/
, die erste Zeile zu ändern und den Rest zu löschen:
sed '/text = "/,/"/{ # in this range
/text = "/!d # delete all lines not matching text = "
s/\\/"/ # replace the backslash with quotes (this is only
}' infile # executed if the previous d wasn't executed)
Auch hier gnu sed
können Sie es als Einzeiler schreiben:
sed '/text = "/,/"/{/text = "/!d;s/\\/"/}' infile
Antwort3
"
Persönlich würde ich das in Perl machen. Wenn wir davon ausgehen können, dass vor dem schließenden kein steht "
, können Sie Folgendes tun:
perl -0pe 's/(text\s*=\s*)".*?"/$1""/s' file
Das -0
saugt die gesamte Datei aus und liest sie in den Speicher. Das -p
bedeutet „drucke jede Zeile (hier ist eine „Zeile“ die gesamte Datei) nach dem Anwenden des durch -e
„“ angegebenen Skripts. Das Skript selbst ist ein einfacher Substitutionsoperator. Es erfasst die Zeichenfolge, text
gefolgt von 0 oder mehr Leerzeichen, einem =
und 0 oder mehr Leerzeichen ( text\s*=\s*
) und speichert sie als $1
. Dann ersetzt es das erfasste Muster sowie die kürzeste zitierte Zeichenfolge, die es findet, durch das Muster ( $1
) und ""
. Das s
Flag sorgt für .
Übereinstimmung mit Zeilenumbrüchen.