Ersetzen Sie das Muster in einer Datei durch den Inhalt einer anderen Datei

20

Ich habe eine Textdatei ( devel.xml).

Ich habe das Wort REPLACETHIS hinzugefügt, um diese Zeichenfolge durch den Inhalt in einer anderen Datei zu ersetzen ( temp.txt).

Das Nächste, was ich habe, ist folgendes:

sed -i -e "/REPLACETHIS/r temp.TXT" -e "s///" devel.txt;

Dadurch wird der Inhalt nach der Zeichenfolge eingefügt und die Zeichenfolge anschließend gelöscht.

Ist das der beste Weg, es zu tun?

RafaelGP
quelle
Muss es sed sein? Je nachdem, wie viel Text in der Datei temp.txt enthalten ist, kann ich auf eine Perl-Lösung umsteigen.
user17591

Antworten:

34

Was Sie getan haben, ist zu entfernen, SUBSTITUTETHISwo immer es in der Datei erscheint (aber nicht der Rest der Zeile, in der es erscheint) und den Inhalt temp.TXTunterhalb dieser Zeile einzufügen . Wenn SUBSTITUTETHISmehrmals in einer Zeile angezeigt wird, wird nur das erste Vorkommen entfernt und nur eine Kopie von temp.TXThinzugefügt.

Wenn Sie die gesamte Zeile ersetzen möchten, wenn SUBSTITUTETHISangezeigt wird, verwenden Sie den dBefehl. Da Sie beide ausführen müssen rund dwenn es ein Match gibt, ordnen Sie sie einer geschweiften Gruppe zu.

sed -e '/SUBSTITUTETHIS/ {' -e 'r temp.TXT' -e 'd' -e '}' -i devel.txt

In einigen sed-Implementierungen können Sie Befehle durch Semikolons trennen und Trennzeichen in geschweiften Klammern weglassen. Sie benötigen jedoch weiterhin eine neue Zeile, um das Argument für den rBefehl zu beenden :

sed -e '/SUBSTITUTETHIS/ {r temp.TXT
                          d}' -i devel.txt

Wenn Sie SUBSTITUTETHISden Inhalt der Datei durch den Inhalt der Datei ersetzen möchten , aber das, was vor und nach der Datei in der Zeile steht, beibehalten möchten , ist dies komplizierter. Die einfachste Methode besteht darin, den Inhalt der Datei in den Befehl sed aufzunehmen. Beachten Sie, dass Sie den Inhalt korrekt zitieren müssen.

sed -e "s/SUBSTITUTETHIS/$(<temp.TXT sed -e 's/[\&/]/\\&/g' -e 's/$/\\n/' | tr -d '\n')/g" -i devel.txt

Oder verwenden Sie Perl. Dies ist kurz, wird jedoch catfür jede Ersetzung einmal ausgeführt:

perl -pe 's/SUBSTITUTETHIS/`cat temp.TXT`/ge' -i devel.txt

So lesen Sie die Datei einmal beim Start des Skripts und vermeiden, dass Sie von einem Shell-Befehl abhängig sind:

perl -MFile::Slurp -pe 'BEGIN {$r = read_file("temp.TXT"); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt

(Zur besseren Lesbarkeit auf zwei Zeilen dargestellt, Sie können jedoch den Zeilenumbruch weglassen.) Wenn der Dateiname variabel ist, übergeben Sie ihn über eine Umgebungsvariable an das Skript, um Anführungszeichen zu vermeiden:

replacement_file=temp.TXT perl -MFile::Slurp -pe 'BEGIN {$r = read_file($replacement_file); chomp($r)}
                        s/SUBSTITUTETHIS/$r/ge' -i devel.txt
Gilles 'SO - hör auf böse zu sein'
quelle
Wie könnte ich den Perl-Befehl ändern, damit cat temp.txtich das tun kann cat ${variable}?
Maria Ines Parnisari
@MariaInesParnisari Bei der Formatierung der Kommentare ist mir ein Fehler unterlaufen. Siehe meine Antwort mit einer etwas anderen, robusteren Lösung.
Gilles 'SO- hör auf böse zu sein'
Da File :: Slurp nicht immer installiert ist, besteht eine Alternative darin, den -0777Schalter zu verwenden , um die gesamte Datei zu schlürfen, und einen regulären open:perl -0777 -pe 'BEGIN {open F, q(temp.TXT); $r=<F>; chomp($r)} s/SUBSTITUTETHIS/$r/ge' -i devel.txt
mivk
Wie man r temp.TXTNachrichten wie "BEGIN temp.TXT", "END temp.TXX"
umbricht
Ich habe eine Lösung für meine Frage gefunden. Verwenden aSie den Befehl (Hinzufügen). grymoire.com/Unix/Sed.html#uh-36
kyb