Ersetzen Sie eine lange Zeichenfolge durch den Befehl sed: Fehler „Argumentliste zu lang“

Ersetzen Sie eine lange Zeichenfolge durch den Befehl sed: Fehler „Argumentliste zu lang“

Ich versuche diesen Befehl auszuführen

sed -i -e "s/BASE_64/$BASE_64/" FILE_NAME

wobei es $BASE_64sich um eine Base64-Darstellung eines Dateiinhalts handelt.

sedgibt mir einen Fehler, da die Zeichenfolge zu lang ist.

Argumentliste zu lang

Wie kann dieser Fehler vermieden werden?

Antwort1

sedSie könnten immer Folgendes tun (da Sie bereits GNU ( ) verwenden -i):

sed -i -f - FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF

-f -weist an sed, das Sed-Skript von stdin zu lesen.

Wenn Sie unter Linux (und nur Linux) mit einer Shell wie und einer Version bis zu 5.0, zshdie Here-Dokumente mit temporären Dateien implementiert (im Gegensatz zu Pipes wie oder (oder 5.1+) für relativ kleine Heredocs und immer noch mit GNU ) , kshdasselbe Skript für mehrere Dateien wiederverwenden möchten , können Sie Folgendes tun:bashdashyashbashsed

find . -name '*.conf' -exec sed -i -f /dev/stdin {} + << EOF
s/BASE_64/$BASE_64/g
EOF

Unter Linux (und nur Linux und Cygwin) /dev/stdinbedeutet dies nichtstdinauf die gleiche Weise -. Stattdessen handelt es sich um einen symbolischen Link zu der Datei, die auf stdin geöffnet wird, sodass seddie Datei bei jedem Öffnen von Anfang an neu geöffnet wird. Der obige Befehl würde auf anderen Systemen (die über verfügen /dev/stdin) oder mit Shells, die Here-Dokumente mit Pipes implementieren, einwandfrei funktionieren, aber nur, wenn nur wenige confDateien vorhanden sind, die sednur einmal aufgerufen werden. Beim zweiten Aufruf auf Nicht-Linux/Cygwin-Systemen, wie mit -f -, /dev/stdinwürde es leer erscheinen, da es bereits beim ersten Aufruf gelesen wurde.

busybox sedunterstützt ebenfalls -iauf die gleiche Weise wie GNU sed, unterstützt jedoch nicht -f -. Sie sollten -f /dev/stdines also auf jeden Fall verwenden. sedVerwenden Sie unter FreeBSD:

sed -i '' -f /dev/stdin FILE_NAME << EOF
s/BASE_64/$BASE_64/g
EOF

Antwort2

Speichern Sie zunächst die Base64-codierten Daten in einer Datei mit dem Namen beispielsweise base64.txt.

Zum Beispiel:

base64 < originalfile > base64.txt

Dann:

printf '%s\n' '/BASE64/r base64.txt' 1 '/BASE64/d' w | ed FILENAME

Dies verwendet edzum Suchen in FILENAMEnach einer Zeile, die die Zeichenfolge enthält BASE64, zum Einfügen des Inhalts von base64.txtnach dieser Zeile, zum Zurückgehen zur ersten Zeile, zum BASE64erneuten Suchen nach der Zeile mit der Zeichenfolge und zum Löschen dieser. Der wBefehl in edspeichert die geänderte Datei.

Antwort3

Eine andere Möglichkeit wäre, seddurch zu ersetzen edund Ihre Befehle in einer Datei zu speichern. Wenn Sie beispielsweise ed_cmdsmit folgendem Inhalt erstellen:

%s/BASE_64/<expanded variable>/g
w
q

du könntest dann laufen

< ed_cmds ed FILE_NAME

und es würde die gewünschten Änderungen vornehmen, sodass $BASE_64Sie anstelle der Einstellung die ed-Befehlsdatei erstellen würden.

Ed Erklärung

  • %bedeutet, den Befehl auf jede Zeile der Datei anzuwenden
  • s/pat1/pat2/gersetzt Vorkommen von pat1durch pat2und gam Ende bewirkt, dass es dies für jede Übereinstimmung in der Zeile tut, nicht nur für die erste
  • wSchreiben Sie die Änderungen auf die Festplatte
  • qbeenden (was sowieso passieren würde, wenn es EOF wird)

Natürlich könnten Sie Ihre sedBefehle auch in eine Datei einfügen und verwenden -f, aber wenn Sie das tun und die Datei an Ort und Stelle ändern möchten, können Sie auch verwenden, edanstatt eine temporäre Datei zu erstellen und sie wie sed -ibeschrieben zu verschieben.

Antwort4

Ich habe die Anweisungen schließlich sedin einer Datei abgelegt

SEDCOMMANDS=`tempfile`

und rief

sed -f "$SEDCOMMANDS" -- "$FILE_NAME"

Das ist gut, wenn Sie nicht verwenden sed -i. Wenn Sie die Datei an Ort und Stelle bearbeiten möchten, folgen Siehttps://unix.stackexchange.com/a/284188/149867und fügen Sie die entsprechenden edAnweisungen in eine Datei ein, gefolgt von wund q.

verwandte Informationen