Angenommen, ich habe eine Datei, die mehrere Vorkommen von StringA und StringB enthält. Ich möchte alle Vorkommen von StringA durch StringB und (gleichzeitig) alle Vorkommen von StringB durch StringA ersetzen.
Im Moment mache ich so etwas wie
cat file.txt | sed 's/StringB/StringC/g' | sed 's/StringA/StringB/g' | sed 's/StringC/StringA/g'
Das Problem bei diesem Ansatz ist, dass davon ausgegangen wird, dass StringC nicht in der Datei vorkommt. Obwohl dies in der Praxis kein Problem darstellt, fühlt sich diese Lösung immer noch schmutzig an – das heißt, sie fühlt sich wie eine Gelegenheit an, mehr Unix-Magie zu lernen. 🙂
Akzeptierte Antwort:
Wenn StringB
und StringA
nicht in derselben Eingabezeile erscheinen kann, dann können Sie sed anweisen, die Ersetzung auf eine Weise durchzuführen und es nur auf die andere Weise zu versuchen, wenn die erste gesuchte Zeichenfolge nicht vorkommt.
<file.txt sed -e 's/StringA/StringB/g' -e t -e 's/StringB/StringA/g'
Im Allgemeinen glaube ich nicht, dass es in sed eine einfache Methode gibt. Beachten Sie übrigens, dass die Angabe mehrdeutig ist, wenn StringA
und StringB
überlappen können. Hier ist eine Perl-Lösung, die das ganz linke Vorkommen einer der beiden Zeichenfolgen ersetzt und wiederholt.
<file.txt perl -pe 'BEGIN {%r = ("StringA" => "StringB", "StringB" => "StringA")}
s/(StringA|StringB)/$r{$1}/ge'
Wenn Sie bei POSIX-Tools bleiben möchten, ist awk der richtige Weg. Awk hat kein Primitiv für allgemeine parametrisierte Ersetzungen, also müssen Sie Ihre eigenen rollen.
<file.txt awk '{
while (match($0, /StringA|StringB/)) {
printf "%s", substr($0, 1, RSTART-1);
$0 = substr($0, RSTART);
printf "%s", /^StringA/ ? "StringB" : "StringA";
$0 = substr($0, 1+RLENGTH)
}
print
}'