Ersetzen Sie einen Marker in einer Textdatei durch beliebigen neuen Text

Ersetzen Sie einen Marker in einer Textdatei durch beliebigen neuen Text

Ich habe eine Datei, die Text enthält und - in einer einzigen Zeile - einen Marker, der angibt, wo neuer Inhalt hinzugefügt werden soll

foo
bar
%SUBSTITUTE%
foo

Die Zeile line substitute sollte durch einen neuen mehrzeiligen String ersetzt werden text="some text"(beachten Sie, dass ich den String nicht kenne, er könnte beispielsweise das Ergebnis des Lesens einer Datei sein text=cat "file"``). Das Ergebnis des Ersetzens sollte lauten

foo
bar
some text
%SUBSTITUTE%
foo

Ich hatte eine funktionierende Version, die auf perldieser basierte, aber nicht mehr funktionierte (anscheinend aufgrund einer Änderung der Perl-Version). Jetzt versuche ich, die Zeile mit Standarddienstprogrammen wie trund sedzu ersetzen. Ich habe damit einige Probleme, weil die einzufügende Zeichenfolge beliebige Zeichen enthalten kann, darunter auch Backslashs usw. Ich möchte diese vor dem Einfügen nicht maskieren.

Gibt es eine sichere Möglichkeit, die mit Standardtools funktioniert? Die anderen Fragen, die ich zu dem Problem finde, sind spezielle Lösungen, bei denen der einzufügende Text bekannt ist.

Antwort1

Wenn Sie die GNU-Version von sed haben, sollten Sie den Befehl verwenden können, rum neuen Inhalt aus einer Datei zu lesen und einzufügen und dann die Markierungszeile zu löschen, z. B.

sed '/%SUBSTITUTE%/{
r path/to/newcontent
d
}' file

%SUBSTITUTE%Wenn Sie den Marker beibehalten möchtennachdas Einfügen, das ist schwierig, denn was auch immer Sie tun, die GNU- rErweiterung stellt den Dateiinhalt in die Warteschlange, bis dieEndedes aktuellen Musterzyklus (beibehaltenVorwäre nur eine Frage des Entfernens des dBefehls). Der wahrscheinlich einfachste Weg ist, ihn an die Datei anzuhängen newcontent: Sie können das im Handumdrehen tun, wie

sed '/%SUBSTITUTE%/{
r /dev/stdin
d
}' file < <(sed '$a %SUBSTITUTE%' path/to/newcontent)

Mit einem ganz anderen Ansatz könnten Sie die erste Datei aufteilen %SUBSTITUTE%und dann den neuen Inhalt hinzufügen.

csplit -s file '/%SUBSTITUTE%/'
cat xx00 newcontent xx01

Sie könnten auch eine Bash- readSchleife über die Zeilen der ersten Datei ausführen und die neue Inhaltsdatei caten, wenn Sie die Markierungszeichenfolge finden. Ich habe jedoch in diesem Forum schon viel Kritik dafür bekommen, dass ich Leseschleifen für die Textverarbeitung vorgeschlagen habe. Leider bietet keines von beiden eine Lösung direkt vor Ort.

Antwort2

Hier ist eine weitere Möglichkeit mit ed.
Fügen Sie den gesamten Inhalt von FILEvor der Markierung ein (also vor der Zeile, die enthält %SUBSTITUTE%):

ed -s originalfile <<< $'/%SUBSTITUTE%/- r FILE\nw\nq'

wobei:
/%SUBSTITUTE%/: Adresse auf die erste passende Zeile setzt %SUBSTITUTE%
-oder -1: Adresse eine Zeile davor verschiebt
r FILE: Reads FILE to after the addressed line.
w: schreibt in originalfile(ersetzen durch , ,pum den Inhalt nur auszudrucken statt zu schreiben)
q: Editor beenden

Das Ersetzen FILEdurch !echo "$TEXT"fügt den Inhalt von $TEXTvor der Markierung ein:

export TEXT
ed -s originalfile <<'IN'
/%SUBSTITUTE%/-1 r !echo "$TEXT"
w
q
IN

Antwort3

Ich habe die folgende Lösung gefunden, basierend auf awk:

text=`cat "filepaste"`
export text;
<"$file" awk '
    BEGIN {REPLACE=ENVIRON["text"] "\n%SUBSTITUTE%" }
    {gsub(/^%SUBSTITUTE%$/, REPLACE); print}
'

Hier enthält "filepaste" den Inhalt, der ersetzt werden soll %SUBSTITUTE%. Ein Vorteil ist, dass dieser String mit verschiedenen Shell-Tools bearbeitet werden kann, ohne dass er wieder in einer Datei gespeichert werden muss. Das Lesen der awkVariable REPLACEaus der Umgebungsvariable vermeidet die Erweiterung von Escape-Zeichen in text.

Antwort4

Da Sie eine Perl-Lösung hatten, hier ist eine weitere. Ich verwende rep.txtzum Speichern des Ersatzes:

$ perl -pe '$re=`cat rep.txt`; chomp($re); s/%SUBSTITUTE%\n/$re/' file.txt
foo
bar
multi
  line
string
foo

Dieses liest jede Zeile der Zieldatei ( file.txt), wendet dann das von angegebene Skript -edarauf an und druckt ( -p).

verwandte Informationen