Wie verwende ich sed, um in einen in einer Variablen gespeicherten Dateinamen zu schreiben?

Wie verwende ich sed, um in einen in einer Variablen gespeicherten Dateinamen zu schreiben?

bashWie kann ich aus einem Skript heraus sedin 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 file1und file2sind 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 sedBefehls. Und ich möchte das Ganze als einzelnes Argument belassen, das an den sedBefehl ü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 wfilesoll 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 herewerden die übereinstimmenden Zeilen in einer Datei mit dem Namen gespeichert, whatever;d;}wobei whateverdas steht, was $file1daraus 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, lin 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 -eArgumente:

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

verwandte Informationen