Antworten:
Verwenden Sie ein alternatives Regex-Trennzeichen, sed
mit dem Sie ein beliebiges Trennzeichen ( einschließlich Steuerzeichen ) verwenden können:
sed "s~$var~replace~g" $file
$var
Eine reine Bash-Antwort: Verwenden Sie die Parametererweiterung , um Schrägstriche in der Variablen rückgängig zu machen:
var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file
${parameter/pattern/string}
. In diesem Fall ist der Parameter also var
das Muster /\/
und die Zeichenfolge \\/
. Alle Instanzen des Musters werden ersetzt, da das Muster mit a beginnt /
.
Die Verwendung von /
in sed als Trennzeichen führt zu Konflikten mit den Schrägstrichen in der Variablen, wenn diese ersetzt werden, und als Ergebnis wird eine Fehlermeldung angezeigt. Eine Möglichkeit, dies zu umgehen, besteht darin, ein anderes Trennzeichen zu verwenden, das für alle Zeichen in dieser Variablen eindeutig ist.
var="/Users/Documents/name/file"
Sie können das Octothorpe-Zeichen verwenden, das zum Anlass passt (oder jedes andere Zeichen, das nicht einfach zu /
bedienen ist).
sed "s#$var#replace#g"
oder
sed 's#$'$var'#replace#g'
Dies ist geeignet, wenn die Variable keine Leerzeichen enthält
oder
sed 's#$"'$var'"#replace#g'
Es ist klüger, das oben Gesagte zu verwenden, da wir daran interessiert sind, alles in dieser Variablen zu ersetzen, anstatt den gesamten Befehl doppelt in Anführungszeichen zu setzen, was dazu führen kann, dass Ihre Shell jedes Zeichen interpetiert, das als spezielles Shell-Zeichen für die Shell angesehen werden könnte.
$var
enthält ~
, müssen Sie natürlich ein anderes Trennzeichen auswählen. Der Fehler "nicht abgeschlossen" klingt so, als ob Ihr Fehler $var
eine neue Zeile enthält. Sie können das Problem möglicherweise beheben, indem Sie jede neue Zeile im Wert mit einem Backslash versehen, aber ich denke nicht, dass dies vollständig portabel ist. Dies hängt im Großen und Ganzen nicht mit dem Problem der Schrägstriche im Wert zusammen.
sed -i "s~blah~$var~g" file
mit Anführungszeichen nur um das eigentliche sed
Skript.
Dies ist eine alte Frage, aber keine der Antworten hier behandelt andere Operationen als s/from/to/
ausführlich.
Die allgemeine Form einer sed
Aussage ist
*address* *action*
Dabei kann die Adresse ein Regex-Bereich oder ein Zeilennummernbereich sein (oder leer. In diesem Fall wird die Aktion auf jede Eingabezeile angewendet). So zum Beispiel
sed '1,4d' file
löscht die Zeilen 1 bis 4 (die Adresse ist der Zeilennummernbereich 1,4
und die Aktion ist der d
Löschbefehl); und
sed '/ick/,$s/foo/bar/' file
werde das erste Vorkommen ersetzen foo
mit bar
auf jeder Leitung zwischen dem ersten Spiel auf dem regulären Ausdruck ick
und das Ende der Datei (die Adresse ist die Reichweite /ick/,$
und die Aktion ist das s
Ersatzbefehl s/foo/bar/
).
In diesem Zusammenhang ick
könnten Sie dies tun , wenn Sie von einer Variablen stammen
sed "/$variable/,\$s/foo/bar/"
(Beachten Sie die Verwendung von doppelten Anführungszeichen anstelle von einfachen Anführungszeichen, damit die Shell die Variable interpolieren kann, und die Notwendigkeit, das wörtliche Dollarzeichen in doppelten Anführungszeichen zu setzen.) Wenn die Variable jedoch einen Schrägstrich enthält, wird ein Syntaxfehler angezeigt. (Die Shell erweitert die Variable und übergibt die resultierende Zeichenfolge an sed
; sed
sieht also nur Literaltext - sie hat kein Konzept für die Variablen der Shell.)
Die Lösung besteht darin, ein anderes Trennzeichen zu verwenden (wobei Sie natürlich in der Lage sein müssen, ein Zeichen zu verwenden, das im Wert der Variablen nicht vorkommen kann). Im Gegensatz zu diesem s%foo%bar%
Fall benötigen Sie jedoch auch einen Backslash vor dem Trennzeichen, wenn Sie ein anderes Trennzeichen verwenden möchten Trennzeichen als Standard /
:
sed "\\%$variable%,\$s/foo/bar/" file
(In einfachen Anführungszeichen würde ein einziger Backslash offensichtlich ausreichen); oder Sie können jeden Schrägstrich im Wert separat maskieren. Diese spezielle Syntax ist nur Bash:
sed "/${variable//\//\\/}/,\$s/foo/bar/" file
oder wenn Sie eine andere Shell verwenden, versuchen Sie es
escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file
Aus Gründen der Klarheit wären die obigen Befehle äquivalent zu , wenn $variable
sie die Zeichenfolge enthalten 1/2
würden
sed '\%1/2%,$s/foo/bar/' file
im ersten Fall und
sed '/1\/2/,$s/foo/bar/' file
in dieser Sekunde.
Verwenden Sie Perl, bei dem Variablen erstklassige Bürger sind und nicht nur Makros erweitern:
var=/Users/Documents/name/file perl -pe 's/\Q$ENV{var}/replace/g' $file
-p
liest die Eingabe zeilenweise und druckt die Zeile nach der Verarbeitung\Q
zitiert alle Metazeichen in der folgenden Zeichenfolge (wird für den hier dargestellten Wert nicht benötigt, ist jedoch erforderlich, wenn der Wert enthalten ist [
oder einige andere Werte, die für reguläre Ausdrücke speziell sind).