In meinem Bash-Skript habe ich eine externe (vom Benutzer empfangene) Zeichenfolge, die ich in sed pattern verwenden sollte.
REPLACE="<funny characters here>"
sed "s/KEYWORD/$REPLACE/g"
Wie kann ich der $REPLACE
Zeichenfolge entkommen, damit sie sicher sed
als wörtlicher Ersatz akzeptiert wird ?
HINWEIS: Das KEYWORD
ist eine dumme Teilkette ohne Streichhölzer usw. Es ist nicht vom Benutzer bereitgestellt.
outputvar="${inputvar//"$txt2replace"/"$txt2replacewith"}".
Antworten:
Warnung : Dies berücksichtigt keine Zeilenumbrüche. Eine ausführlichere Antwort finden Sie stattdessen in dieser SO-Frage . (Danke, Ed Morton & Niklas Peter)
Beachten Sie, dass es eine schlechte Idee ist, alles zu entkommen. Sed braucht viele Charaktere, um entkommen zu können, um ihre besondere Bedeutung zu erhalten. Wenn Sie beispielsweise eine Ziffer in der Ersatzzeichenfolge maskieren, wird daraus eine Rückreferenz.
Wie Ben Blank sagte, müssen nur drei Zeichen in der Ersatzzeichenfolge maskiert werden (maskiert sich selbst, Schrägstrich für das Ende der Anweisung und & für alle ersetzen):
Wenn Sie jemals aus der
KEYWORD
Zeichenfolge entkommen müssen, benötigen Sie Folgendes:Und kann verwendet werden von:
Denken Sie daran, wenn Sie ein anderes Zeichen
/
als Trennzeichen verwenden, müssen Sie den Schrägstrich in den obigen Ausdrücken durch das von Ihnen verwendete Zeichen ersetzen. Erläuterungen finden Sie im Kommentar von PeterJCLaw.Bearbeitet: Aufgrund einiger Eckfälle, die zuvor nicht berücksichtigt wurden, haben sich die obigen Befehle mehrmals geändert. Überprüfen Sie den Bearbeitungsverlauf auf Details.
quelle
KEYWORD
in GNU sed sind hier 2 weitere Zeichen^
,$
die oben nicht erwähnt wurden:s/[]\/$*.^|[]/\\&/g
A='foo"bar' echo $A | sed s/$A/baz/
In Bash. Die doppelten Anführungszeichen werden genauso behandelt wie die 'foo' und 'bar' um sie herum.Mit dem Befehl sed können Sie andere Zeichen anstelle des
/
Trennzeichens verwenden:Die doppelten Anführungszeichen sind kein Problem.
quelle
.
was sonst eine besondere Bedeutung hat. Ich habe deine Antwort bearbeitet.sed '/CLIENTSCRIPT="foo"/a CLIENTSCRIPT2="hello"' file
mitsed '|CLIENTSCRIPT="foo"|a CLIENTSCRIPT2="hello"' file
und das macht nicht das gleiche.s
Befehl (wie im Ersatz) von sed können Sie andere Zeichen anstelle von / als Trennzeichen verwenden. Dies wäre auch eine Antwort auf die Verwendung von sed on URL mit Schrägstrichen. Es beantwortet nicht die OP-Frage, wie eine von einem Benutzer eingegebene Zeichenfolge maskiert werden kann, die /, \, aber auch # enthalten könnte, wenn Sie sich dafür entscheiden, diese zu verwenden. Und außerdem kann URI auch # enthaltenDie einzigen drei Literalzeichen, die in der Ersetzungsklausel speziell behandelt werden, sind
/
(um die Klausel zu schließen),\
(um Zeichen, Rückreferenzen usw. zu umgehen) und&
(um die Übereinstimmung in die Ersetzungsklausel aufzunehmen). Daher müssen Sie nur diesen drei Zeichen entkommen:Beispiel:
quelle
Basierend auf den regulären Ausdrücken von Pianosaurus habe ich eine Bash-Funktion erstellt, die sowohl dem Schlüsselwort als auch der Ersetzung entgeht.
So verwenden Sie es:
quelle
man echo
), was dazu führt, dass sich die Pipe unerwartet verhält, wenn Ihr Argument$1
mit einem Bindestrich beginnt. Stattdessen können Sie Ihre Pipe mit beginnenprintf '%s\n' "$1"
.Es ist etwas spät zu antworten ... aber es gibt einen viel einfacheren Weg, dies zu tun. Ändern Sie einfach das Trennzeichen (dh das Zeichen, das die Felder trennt). Also, anstatt dass
s/foo/bar/
du schreibsts|bar|foo
.Und hier ist der einfache Weg, dies zu tun:
Die resultierende Ausgabe enthält keine böse DEFINER-Klausel.
quelle
&
und `` muss noch maskiert werden, ebenso wie das Trennzeichen, je nachdem, was gewählt wird.$
in der zu ändernden Zeichenfolge zu entkommen und die Bedeutung$
der Ersatzzeichenfolge beizubehalten . Angenommen, ich möchte zum$XXX
Wert der Variablen wechseln$YYY
,sed -i "s|\$XXX|$YYY|g" file
funktioniert einwandfrei.Es stellt sich heraus, dass Sie die falsche Frage stellen. Ich habe auch die falsche Frage gestellt. Der Grund, warum es falsch ist, ist der Anfang des ersten Satzes: "In meinem Bash- Skript ...".
Ich hatte die gleiche Frage und machte den gleichen Fehler. Wenn Sie bash verwenden, müssen Sie sed nicht verwenden, um Zeichenfolgen zu ersetzen (und es ist viel sauberer, die in bash integrierte Ersetzungsfunktion zu verwenden).
Anstelle von zum Beispiel:
Sie können ausschließlich Bash-Funktionen verwenden:
quelle
$A
und$B
ist nicht zitiert, aber sie sind es nicht. Die Anführungszeichen innerhalb von${}
stimmen nicht mit den Anführungszeichen außerhalb überein.var='has space'
) -OUTPUT=${INPUT//"$A"/"$B"}
ist sicher.Verwenden Sie awk - es ist sauberer:
quelle
awk
ist, dass es nichts Ähnliches gibtsed -i
, was in 99% der Fälle äußerst praktisch ist.Hier ist ein Beispiel für eine AWK, die ich vor einiger Zeit verwendet habe. Es ist eine AWK, die neue AWKS druckt. Da AWK und SED ähnlich sind, kann dies eine gute Vorlage sein.
Es sieht übertrieben aus, aber irgendwie funktioniert diese Kombination von Zitaten, um das 'als Literale gedruckt zu halten. Wenn ich mich richtig erinnere, sind die vaiables nur von Anführungszeichen wie diesem umgeben: "$ 1". Probieren Sie es aus, lassen Sie mich wissen, wie es mit SED funktioniert.
quelle
Ich habe eine Verbesserung gegenüber der Sedeasy-Funktion, die mit Sonderzeichen wie Tab brechen wird.
Also, was ist anders?
$1
und$2
in Anführungszeichen gesetzt, um Shell-Erweiterungen zu vermeiden und Tabulatoren oder doppelte Leerzeichen beizubehalten.Zusätzliche Rohrleitungen
| sed -e 's:\t:\\t:g'
(ich mag:
als Token), die eine Registerkarte in transformieren\t
.quelle
Dies sind die Fluchtcodes, die ich gefunden habe:
quelle
Vergessen Sie nicht all das Vergnügen, das mit der Shell-Begrenzung um "und '
also (in ksh)
quelle
Wenn Sie nur den Variablenwert im Befehl sed ersetzen möchten, entfernen Sie einfach Beispiel:
quelle
Wenn Sie zufällig ein zufälliges Kennwort generieren, das zum
sed
Ersetzen des Musters übergeben werden soll, müssen Sie vorsichtig sein, welcher Zeichensatz in der zufälligen Zeichenfolge enthalten ist. Wenn Sie ein Kennwort auswählen, das durch Codieren eines Werts als base64 erstellt wurde, gibt es nur Zeichen, die sowohl in base64 als auch als Sonderzeichen imsed
Ersetzungsmuster möglich sind. Dieses Zeichen ist "/" und kann leicht aus dem von Ihnen generierten Passwort entfernt werden:quelle
Eine einfachere Möglichkeit, dies zu tun, besteht darin, die Zeichenfolge einfach vorher zu erstellen und als Parameter für zu verwenden
sed
quelle
REPLACE=/
gibtsed: -e expression #1, char 12: unknown option to `s'