Nimm das folgende Skript:
#!/bin/sh
sed 's/(127\.0\.1\.1)\s/\1/' [some file]
Wenn ich versuche, dies sh
( dash
hier) auszuführen , schlägt dies aufgrund der Klammern fehl, die maskiert werden müssen. Aber ich muss den Backslashes selbst nicht entkommen (zwischen den Oktetten oder im \s
oder \1
). Was ist die Regel hier? Was ist, wenn ich {...}
oder verwenden muss [...]
? Gibt es eine Liste von dem, was ich tue und was ich nicht entkommen muss?
shell-script
sed
quoting
tückisch
quelle
quelle
function sedPath { path=$((echo $1|sed -r 's/([\$\.\*\/\[\\^])/\\\1/g'|sed 's/[]]/\[]]/g')>&1) } #Escape path for use with sed
Antworten:
Hier gibt es zwei Interpretationsebenen: die Shell und sed.
In der Shell wird alles zwischen einfachen Anführungszeichen wörtlich interpretiert, mit Ausnahme von einfachen Anführungszeichen. Sie können effektiv ein einfaches Anführungszeichen zwischen einfachen Anführungszeichen setzen, indem Sie schreiben
'\''
( einfaches Anführungszeichen schließen, einfaches Anführungszeichen wörtlich, einfaches Anführungszeichen öffnen).Sed verwendet grundlegende reguläre Ausdrücke . In einer BRE müssen die Zeichen
$.*[\^
in Anführungszeichen gesetzt werden, damit sie buchstäblich behandelt werden, mit Ausnahme der in Zeichensätzen ([…]
) enthaltenen Schrägstriche . Buchstaben, Ziffern und(){}+?|
dürfen nicht in Anführungszeichen gesetzt werden (einige davon können in einigen Implementierungen nicht in Anführungszeichen gesetzt werden). Die Sequenzen\(
,\)
,\n
, und in einigen Implementierungen\{
,\}
,\+
,\?
,\|
und andere Backslash + alphanumerics haben eine besondere Bedeutung.$^
In einigen Implementierungen kann es passieren, dass Sie in einigen Positionen nicht zitieren .Darüber hinaus benötigen Sie einen Backslash, bevor
/
er im regulären Ausdruck außerhalb von Klammern angezeigt werden soll. Sie können ein alternatives Zeichen als Trennzeichen auswählen, indem Sie schreiben, z. B.s~/dir~/replacement~
oder\~/dir~p
; Sie benötigen einen Backslash vor dem Begrenzer, wenn Sie ihn in die BRE aufnehmen möchten. Wenn Sie ein Zeichen auswählen, das in einer BRE eine besondere Bedeutung hat, und es buchstäblich einschließen möchten, benötigen Sie drei umgekehrte Schrägstriche. Ich empfehle dies nicht, da es sich in einigen Implementierungen anders verhalten kann.Kurz gesagt, für
sed 's/…/…/'
:'\''
diese Option, um ein einfaches Anführungszeichen im regulären Ausdruck zu erhalten.$.*/[\]^
und nur diese Zeichen (aber nicht in Klammern). (Technisch gesehen sollte man nicht einen umgekehrten Schrägstrich setzen , bevor]
aber ich weiß nicht von einer Implementierung , die behandelt]
und\]
außerhalb der Klammerausdrücke anders.)-
Um buchstäblich behandelt zu werden, stellen Sie in einem Klammerausdruck sicher, dass er der erste oder letzte ist ([abc-]
oder[-abc]
nicht).[a-bc]
^
Um buchstäblich behandelt zu werden, stellen Sie in einem Klammerausdruck sicher, dass er nicht an erster Stelle steht (use[abc^]
, not).[^abc]
]
in die Liste der Zeichen aufnehmen möchten, die mit einem Klammerausdruck übereinstimmen, geben Sie als erstes Zeichen (oder als erstes nach^
einem negierten Satz) Folgendes an:[]abc]
oder[^]abc]
(weder).[abc]]
noch[abc\]]
Im Ersetzungstext:
&
und\
müssen in Anführungszeichen gesetzt werden, ebenso wie das Trennzeichen (normalerweise/
) und die Zeilenumbrüche.\
gefolgt von einer Ziffer hat eine besondere Bedeutung.\
gefolgt von einem Buchstaben hat in einigen Implementierungen eine spezielle Bedeutung (Sonderzeichen),\
gefolgt von einem anderen Zeichen\c
oderc
abhängig von der Implementierung.sed 's/…/…/'
Verwenden Sie einfache Anführungszeichen um das Argument ( ),'\''
um ein einfaches Anführungszeichen in den Ersetzungstext einzufügen.Wenn der reguläre Ausdruck oder der Ersetzungstext aus einer Shell-Variablen stammt, denken Sie daran
\n
(was niemals zutrifft, es sei denn, Sie haben einen anderensed
Code, der dem Musterraum Zeichen für neue Zeilen hinzufügt). Beachten Sie jedoch, dass dies bei einigensed
Implementierungen nicht in Klammern funktioniert .&
,\
und Zeilenumbrüche zitiert werden.sed -e "s/$BRE/$REPL/"
.quelle
\\*
) verwenden. Beispiel:echo "***NEW***" | sed /\\*\\*\\*NEW\\*\\*\\*/s/^/#/
Das Problem, das Sie haben, liegt nicht an der Shell-Interpolation und an der Escape-Funktion, sondern daran, dass Sie versuchen, die Syntax für erweiterte reguläre Ausdrücke zu verwenden, ohne die Option
-r
oder zu übergeben--regexp-extended
.Ändern Sie Ihre Sed-Linie von
zu
und es wird funktionieren, wie ich glaube, dass Sie beabsichtigen.
Standardmäßig verwendet sed uses grundlegende reguläre Ausdrücke (think grep style), für die die folgende Syntax erforderlich wäre:
quelle
-r
als Option war in meinem Fall erforderlich.Verwenden Sie einfache Anführungszeichen für den gesamten Ausdruck, es sei denn, Sie möchten eine Shell-Variable in den sed-Ausdruck interpolieren, da sie bewirken, dass alles zwischen ihnen so interpretiert wird, wie es ist, einschließlich der umgekehrten Schrägstriche.
Wenn Sie also möchten, dass sed
s/\(127\.0\.1\.1\)\s/\1/
einfache Anführungszeichen sieht , und die Shell die Klammern oder umgekehrten Schrägstriche darin nicht berührt. Wenn Sie eine Shell-Variable interpolieren müssen, setzen Sie nur diesen Teil in doppelte Anführungszeichen. Z.BDadurch sparen Sie sich die Mühe, sich zu merken, welche Shell-Metazeichen nicht durch doppelte Anführungszeichen geschützt sind.
quelle
sed
sehens/(127\.0\.1\.1)/...
, aber das in ein Shell-Skript so wie es ist zu setzen, funktioniert nicht. Was Sie über die Shell sagen, die die Klammern nicht berührt, scheint falsch zu sein. Ich habe meine Frage zum Ausarbeiten bearbeitet.sed 's/(127\.0\.1\.1)/IP \1/'
schlägt fehl, weil sed\(
und\)
für die Gruppensyntax sehen muss, nicht(
und)
.