Um zu entkommen Variablen auf der linken Seite und die rechte Seite eines zu verwendenden s
Befehls in sed
(hier $lhs
und $rhs
respectively), dann würden Sie tun:
escaped_lhs=$(printf '%s\n' "$lhs" | sed 's:[][\/.^$*]:\\&:g')
escaped_rhs=$(printf '%s\n' "$rhs" | sed 's:[\/&]:\\&:g;$!s/$/\\/')
sed "s/$escaped_lhs/$escaped_rhs/"
Beachten Sie, dass $lhs
kein Newline-Zeichen enthalten sein darf.
Dies bedeutet, dass in der LHS alle regulären Ausdrücke ( ][.^$*
), das Escaping-Zeichen selbst ( \
) und das Trennzeichen ( /
) maskiert werden .
Auf dem RHS müssen Sie nur &
das Trennzeichen, den Backslash und das Newline-Zeichen (was Sie tun, indem Sie am Ende jeder Zeile einen Backslash einfügen, mit Ausnahme des letzten ( $!s/$/\\/
)).
Dies setzt voraus, dass Sie /
in Ihren sed
s
Befehlen als Trennzeichen verwenden und Extended REs nicht mit -r
(GNU sed
/ ssed
/ ast
/ busybox sed
) oder -E
(BSDs, ast
Recent GNU, Recent Busy Box) oder PCREs mit -R
( ssed
) oder Augmented REs mit -A
/ -X
( ast
) aktivieren Alle haben zusätzliche RE-Operatoren.
Einige Grundregeln beim Umgang mit beliebigen Daten:
- Nicht verwenden
echo
- Zitieren Sie Ihre Variablen
- Berücksichtigen Sie die Auswirkung des Gebietsschemas (insbesondere seines Zeichensatzes: Es ist wichtig, dass die Escaping-
sed
Befehle in demselben Gebietsschema wie der sed
Befehl ausgeführt werden, z. B. mit den Escaped- Zeichenfolgen (und mit demselben sed
Befehl).
- Vergessen Sie nicht das Newline-Zeichen (hier können Sie überprüfen, ob es
$lhs
vorhanden ist, und Maßnahmen ergreifen).
Eine weitere Möglichkeit ist die Verwendung perl
statt sed
und übergeben Sie die Zeichenfolge in der Umgebung und die Verwendung \Q
/ \E
perl
regexp Operatoren für Strings wörtlich nehmen:
A="$lhs" B="$rhs" perl -pe 's/\Q$ENV{A}\E/$ENV{B}/g'
perl
(Standardmäßig) wird vom Zeichensatz des Gebietsschemas nicht beeinflusst, da oben nur die Zeichenfolgen als Bytearrays betrachtet werden, ohne darauf zu achten, welche Zeichen (falls vorhanden) sie für den Benutzer darstellen. Mit sed
können Sie dasselbe erreichen, indem Sie das Gebietsschema für alle Befehle auf C
mit festlegen (dies wirkt sich jedoch auch auf die Sprache der etwaigen Fehlermeldungen aus).LC_ALL=C
sed