wake-up-neo.com

So übergeben Sie eine Variable, die Schrägstriche enthält, an sed

Wie übergeben Sie eine Variable, die Schrägstriche als Muster enthält, an sed?

Zum Beispiel, wenn ich die folgende Variable habe:

var="/Users/Documents/name/file"

Ich möchte es wie folgt an sed übergeben:

sed "s/$var/replace/g" "$file"

Ich bekomme jedoch Fehler. Wie kann ich das Problem umgehen?

65
Bolboa

Verwenden Sie ein alternatives Regex-Trennzeichen, da Sie mit sed beliebige Trennzeichen verwenden können ( einschließlich Steuerzeichen ):

sed "s~$var~replace~g" $file
118
anubhava

Eine reine Antwort auf die Bash: Verwenden Sie Parametererweiterung , um alle Schrägstriche in der Variablen rückwärts zu umgehen:

var="/Users/Documents/name/file"
sed "s/${var//\//\\/}/replace/g" $file
38
glenn jackman

Eine andere Möglichkeit, dies zu tun, ist zwar hässlicher als die Antwort von anubhava, indem alle Backslashes in var mit einem anderen sed-Befehl umgangen werden:

var=$(echo "$var" | sed 's/\//\\\//g')

dann wird das funktionieren:

sed "s/$var/replace/g" $file
25
Bolboa

Die Verwendung von / in sed als Trennzeichen führt bei der Ersetzung zu Konflikten mit den Schrägstrichen in der Variablen. Als Ergebnis erhalten Sie einen Fehler. Eine Möglichkeit, dies zu umgehen, besteht darin, ein anderes Trennzeichen zu verwenden, das sich von allen Zeichen dieser Variablen unterscheidet.

var="/Users/Documents/name/file"

sie können das Octothorpe-Zeichen verwenden, das der Gelegenheit entspricht (oder ein beliebiges anderes Zeichen, das kein / 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, den obigen Befehl zu verwenden, da wir daran interessiert sind, nur das zu ersetzen, was in dieser Variablen enthalten ist, im Vergleich zu einem doppelten Anführungszeichen des gesamten Befehls, der dazu führen kann, dass Ihre Shell jedes Zeichen interpetiert, das als spezielles Shell-Zeichen für die Shell gelten könnte.

7
repzero

Dies ist eine alte Frage, aber in keiner der Antworten werden andere Operationen als s/from/to/ ausführlich beschrieben.

Die allgemeine Form einer sed-Anweisung lautet

*address* *action*

wobei address ein Regex-Bereich oder ein Zeilennummernbereich sein kann (oder leer, in diesem Fall wird die Aktion auf jede Eingabezeile angewendet). Also 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

ersetzt das erste Vorkommen von foo durch bar in einer beliebigen Zeile zwischen der ersten Übereinstimmung auf dem regulären Ausdruck ick und dem Ende der Datei (die Adresse ist der Bereich /ick/,$ und die Aktion ist der s Ersetzungsbefehl s/foo/bar/ ).

Wenn ick von einer Variablen stammt, können Sie dies tun

sed "/$variable/,\$s/foo/bar/"

(Beachten Sie die Verwendung von doppelten Anführungszeichen anstelle von einfachen Anführungszeichen, sodass die Shell die Variable interpolieren kann, und Sie müssen das Dollarzeichen in doppelte Anführungszeichen 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; daher sieht sed nur wörtlichen Text - sie hat keine Vorstellung von den Variablen der Shell.)

Die Lösung besteht in der Verwendung eines anderen Begrenzungszeichens (bei dem Sie offensichtlich ein Zeichen verwenden müssen, das im Wert der Variablen nicht vorkommen kann). Wenn Sie jedoch ein Zeichen verwenden möchten, benötigen Sie im Gegensatz zum Fall s%foo%bar% auch einen Backslash vor dem Begrenzungszeichen anderes Trennzeichen als der Standard /:

sed "\\%$variable%,\$s/foo/bar/" file

(In einfachen Anführungszeichen würde offensichtlich ein einzelner Backslash ausreichen); oder Sie können jedem Schrägstrich im Wert separat entgehen. Diese bestimmte Syntax ist nur Bash:

sed "/${variable//\//\\/}/,\$s/foo/bar/" file

wenn Sie eine andere Shell verwenden, versuchen Sie es

escaped=$(echo "$variable" | sed 's%/%\\/%g')
sed "s/$escaped/,\$s/foo/bar/" file

Wenn der Code $variable die Zeichenfolge 1/2 enthält, wären die obigen Befehle zur Vereinfachung äquivalent zu

sed '\%1/2%,$s/foo/bar/' file

im ersten Fall und

sed '/1\/2/,$s/foo/bar/' file

in dieser Sekunde.

3
tripleee

Verwenden Sie Perl, wobei 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 Zeile für Zeile und druckt die Zeile nach der Verarbeitung
  • \Q zitiert alle Metazeichen in der folgenden Zeichenfolge (wird für den hier angezeigten Wert nicht benötigt, ist jedoch erforderlich, wenn der Wert [ oder einige andere für reguläre Ausdrücke bestimmte Werte enthält)
0
choroba