Ersetzen Sie den String mit sed durch den Inhalt einer Datei

23

Ich habe zwei verschiedene Dateien:

Datei1

/home/user1/  
/home/user2/bin  
/home/user1/a/b/c

Datei2

<TEXT1>
<TEXT2>

Ich möchte das <TEXT1>von File2 mit dem Inhalt von File1 ersetzen, das verwendet sed. Ich habe diesen Befehl ausprobiert, erhalte aber keine korrekte Ausgabe:

cat File2|sed "s/<TEXT1>/$(cat File1|sed 's/\//\\\//g'|sed 's/$/\\n/g'|tr -d "\n")/g"

Sie können auch andere Tools verwenden, um dieses Problem zu lösen.

chanchal1987
quelle
Bitte fügen Sie diese Fehlermeldung ein, damit wir ihre Quelle finden können. Sagen Sie uns auch, welche sedImplementierung Sie verwenden. Ihr Code funktioniert für mich mit GNU sed.
Manatwork
Entschuldigung, es wird kein Fehler angezeigt. Ich erhalte keine gewünschte Ausgabe. Ausgabe ist wie /home/user1/ n/home/user2/bin n/home/user1/a/b/cn <TEXT2>. Keine neuen Zeilen bekommen.
chanchal1987
Ich bin mir nicht sicher, ob dies in Ihrem speziellen Fall zutreffen würde, aber mit diffund patchkönnen einige Zeilen in einer Datei ganz einfach durch andere Zeilen ersetzt werden.
Stéphane Gimenez
1
Übrigens, $()wenn ich zufällige Daten verwende, die in einem Sed-Skript gesammelt wurden, bluten meine Augen. Verwenden Sie niemals externe Daten an Stellen, an denen bestimmte Zeichen mit besonderer Bedeutung interpretiert werden.
Stéphane Gimenez

Antworten:

24

Hier ist eine sed-Skript-Lösung (einfacher für die Augen, als zu versuchen, sie in einer Zeile in der Befehlszeile zusammenzufassen):

/<TEXT1>/ {
  r File1
  d
}

Laufen es:

$ sed -f script.sed File2
/home/user1/
/home/user2/bin
/home/user1/a/b/c
<TEXT2>
Kusalananda
quelle
Danke, das funktioniert. Aber ich möchte keine andere Skriptdatei verwenden. Gibt es eine Inline-Lösung?
Chanchal1987
Klar:, sed '/<TEXT1>/{rFile1^Md^M}' File2wo "^ M" drückt man die Eingabetaste. Das Problem ist, dass sed wirklich die Zeilenumbrüche innerhalb von {...} benötigt, um den Befehl r und den Befehl d abzugrenzen.
Kusalananda
6
mit bash sind saiten im posix-stil etwas sauberer:sed $'/<TEXT1>/ {r File1\n d}'
glenn jackman
9
Auch mit -e für einen sed -e '/<TEXT1>/{r File1' -e 'd}' File2
Einzeiler
1
Und was ist, wenn <TEXT1>ich, anstatt die gesamte Zeile zu ersetzen, nur die Zeichenfolge selbst ersetzen und den Rest der Zeile intakt lassen möchte? Text1: <TEXT1>zu Text1: <file_contents>.
Robin Winslow
9

Ich habe lange gebraucht, um diese Lösung mit var replacement zu finden. Alle sed-Lösungen haben bei mir nicht funktioniert, da sie entweder komplette Zeilen löschen oder falsch ersetzen.

FILE2=$(<file2)
FILE1=$(<file1)
echo "${FILE2//TEXT1/$FILE1}" 

Ersetzt alle Vorkommen von TEXT1 in Datei2 gegen den Inhalt von Datei1. Alle anderen Texte bleiben unberührt.

marcas756
quelle
Sehr schön. Möglicherweise auch schneller sed, da diese "Erweiterungen" (auch bekannt als Ersatz) ( bashzumindest) in die Shell eingebaut sind
zartgelb
7

Ich antworte, weil die diff/ patch-Methode in einigen Fällen von Interesse sein könnte. So definieren Sie eine Ersetzung der in der Datei blob1enthaltenen Zeilen durch die in der blob2Verwendung enthaltenen Zeilen :

diff -u blob1 blob2 > patch-file

Zum Beispiel, wenn blob1enthält:

hello
you

und blob2enthält:

be
welcome
here

das erzeugte patch-filewird sein:

--- blob1   2011-09-08 16:42:24.000000000 +0200
+++ blob2   2011-09-08 16:50:48.000000000 +0200
@@ -1,2 +1,3 @@
-hello
-you
+be
+welcome
+here

Jetzt können Sie diesen Patch auf jede andere Datei anwenden:

patch somefile patch-file

Es wird ersetzen hello, youLinien durch be, welcome, hereLinien in somefile.

Stéphane Gimenez
quelle
Das ist wirklich klug, aber es wäre besser, wenn Sie es in einem Skript automatisieren könnten
qodeninja