bash
Wie kann ich aus einem Skript heraus sed
in eine Datei schreiben, deren Dateiname in einer Bash-Variable gespeichert ist? Die Ausgabeumleitung reicht nicht aus, da ich eine Datei direkt bearbeiten und Zeilen, die einem regulären Ausdruck entsprechen, in eine andere Datei ziehen und sie in der ersten Datei löschen möchte.
Etwas wie:
sed -i '/^my regex here$/{;w file2;d;}' file1
...aber wo file1
und file2
sind beide eigentlichVariablenDashaltendie Dateinamen. (Wie zum Beispiel file2=$(mktemp)
.)
Was ich also wirklich möchte, ist eine Variablenerweiterung für den Dateinamen, aber keine Erweiterung für den Rest des sed
Befehls. Und ich möchte das Ganze als einzelnes Argument belassen, das an den sed
Befehl übergeben wird.
Aus irgendeinem Grund funktioniert Folgendes nicht:
sed -i '/my regex here/{;w '"$file2"';d;}' $file1
Dort steht „unmatched {“ und ich kann nicht erkennen, warum.
Kann ich das irgendwie machen?
Antwort1
Da Sie einen einzelnen Ausdruck verwenden sed
, ist alles, was nach dem folgt w
(einschließlich des }
),interpretiert alswDateiName:
Das Argument
wfile
soll den Bearbeitungsbefehl beenden.
Sie können dies erkennen, wenn Sie einen zweiten Befehl hinzufügen, }
beispielsweise wie:
sed -e '/my regex here/{w '"$file2"';d;}' -e '}' $file1
dann my regex here
werden die übereinstimmenden Zeilen in einer Datei mit dem Namen gespeichert, whatever;d;}
wobei whatever
das steht, was $file1
daraus resultiert.
Die korrekte Syntax erfolgt über separate Befehle oder mit mehreren Ausdrücken:
sed -e '/my regex here/{w '"$file1" -e 'd' -e '}' $file2
oder ein Befehl pro Zeile:
sed '/my regex here/{
w '"$file1"'
d
}
' $file2
Antwort2
Die Antwort fand ich aufPaketüberflussunter „Wie teile ich dem sed ‚w‘-Befehl mit, wo der Dateiname endet?“
Wie terdon anmerkte, liegt das Problem nicht an der Variable, aber es hat auch nichts mit den geschweiften Klammern zu tun. Probieren Sie es aus, sed '/^l/w testing;p'
und Sie werden sehen, dass kein Fehler ausgegeben wird, sondern alle Zeilen, die mit einem beginnen, l
in eine Datei mit dem Namen geschrieben werden testing;p
.
Das Problem ist eigentlich das Fehlen einer neuen Zeile nach dem Dateinamen.
Die Antwort besteht also darin, entweder einen Inline-Zeilenumbruch im sed-Befehl zu verwenden:
sed -i '/my regex here/{;w '"$file2"'
d;}' $file1
Oder, was viel sauberer ist, verwenden Sie zwei separate -e
Argumente:
sed -i -e '/my regex here/{;w '"$file2" -e 'd;}' $file1
Wenn Ihnen die beiden angrenzenden Anführungszeichen nicht gefallen (die Ihnen leicht in die Quere kommen könnten), setzen Sie den Schreibbefehl einfach in ein eigenes Argument:
sed -i -e '/^my regex here$/{' -e "w $file2" -e 'd;}' $file1
Antwort3
Verwenden Sie doppelte Anführungszeichen anstelle einfacher Anführungszeichen, um den sed-Befehl zu zitieren. Und vergessen Sie nicht, geeignete Zeichen zu maskieren.
Weitere Informationen zum Zitieren von Variablen in Bash finden Sie hierVerknüpfung