it-swarm.com.de

Ersetzen Sie ein Wort durch mehrere Zeilen mit sed?

Ich arbeite an einem Bash-Skript, das eine E-Mail für den Versand an einen Benutzer vorbereiten muss.

Es aggregiert einige Daten, was letztendlich zu mehreren Datenzeilen führt. Für das in $DATA gespeicherte Beispiel.

Jetzt, nach ein bisschen stfw, habe ich ein paar Dinge wie sed -ei "s/_data_/${DATA}/g" mail.tpl gefunden und auch sed replace with variable with multiple lines . Keiner von ihnen funktioniert.

Nun stellt sich die Frage, wie ich sed dazu bringe, etwas durch mehrere Textzeilen zu ersetzen.

(Alternativen zu sed sind ebenfalls willkommen!)

17
Cobra_Fast

Wenn Sie Ihren mehrzeiligen Text mit "\n" s erstellen, funktioniert dies mit einem einfachen sed-Befehl wie folgt:

DATA=`echo ${DATA} | tr '\n' "\\n"`
#now, DATA="line1\nline2\nline3"
sed "s/_data_/${DATA}/" mail.tpl
11
ring bearer

awk

kent$  cat test
foo
bar
blah _data_and_data_
foo
_data_ foobar _data_ again


kent$  echo $DATA
1
2
3
4
5

kent$  awk -v r=$DATA '{gsub(/_data_/,r)}1' test
foo
bar
blah 1
2
3
4
5and1
2
3
4
5
foo
1
2
3
4
5 foobar 1
2
3
4
5 again
11
Kent

Ich habe es und sed 's/pattern/\na\nb\nc/g' ausprobiert, aber es funktioniert nicht auf allen Systemen. Was funktioniert, ist, einen \ gefolgt von einer neuen Zeile in das Ersetzungsmuster einzufügen, wie beispielsweise:

sed 's/pattern/a\
b\
c/g'

Dies hängt eine Zeile an, die b und eine Zeile enthält, die c enthält, wenn das Muster angezeigt wird.

Um es in eine Variable einzufügen, verwenden Sie doppelte Backslashes:

export DATA="\\
a\\
b\\
c"

und dann:

sed "s/pattern/${DATA}/g"

Beachten Sie die doppelten Anführungszeichen.

9
Albert Veli

Ich würde vorschlagen, sed einfach durch einen Perl-Befehl wie folgt zu ersetzen:

Perl -i.bak -pe 's/_data_/'"${DATA}"'/g' mail.tpl 
8
anubhava

die Antwort des Ringträgers funktionierte nicht für mich; Ich denke, dass die Verwendung von tr dort falsch ist, und wie sie geschrieben wird, entfernt sie einfach Zeilenumbrüche mithilfe von echo.

Stattdessen habe ich sed verwendet. Ich habe Code aus einer anderen Antwort verwendet, um Zeilenumbrüche zu ersetzen (Kredit: Zsolt Botykai). Ich habe auch ein paar Dollarzeichen ($) in meiner Eingabe erwartet, also habe ich mich auch darum gekümmert. Möglicherweise müssen Sie andere Eingabehandlungen hinzufügen. Beachten Sie die Verwendung von Anführungszeichen in echo, um die Zeilenumbrüche zu erhalten.

DATA="$(cat whatever)"
ESCAPED_DATA="$(echo "${DATA}" | sed ':a;N;$!ba;s/\n/\\n/g' | sed 's/\$/\\$/g')"

Dann können Sie ${ESCAPED_DATA} in sed verwenden:

cat input | sed 's/one liner/'"${ESCAPED_DATA}"'/' > output 

Ich dachte nur, ich würde es teilen.

7
Yuval

Alle Zeilenumbrüche mit einem \ (außer dem letzten) zu umgehen, hat für mich funktioniert. Der letzte Zeilenumbruch darf nicht mit Escapezeichen versehen werden, um den Befehl s nicht zu brechen.

Beispiel:

DATA="a
b
c"

ESCAPED=$(echo "${DATA}" | sed '[email protected][email protected]\\@g')
echo "${ESCAPED}" 
a\
b\
c

sed "s/pattern/${ESCAPED}/" file
1
mgraff

Sie können Ihre Daten in eine temporäre Datei packen und ausführen:

$ sed '/_data_/r DATA_FILE' mail.tpl | sed '/_data_/d'> temp; mv temp mail.tpl
0
Mihai

Nicht sicher, ob Sie versucht haben, "\ n" in das Ersetzungsteil zu setzen

sed 's/[pattern]/\
[line 1]\n\
[line 2]\n\
[line n]\n\
/g' mail.tpl

Die erste Zeile enthält/\ aus Gründen der Lesbarkeit. Jede Zeile danach ist eine eigenständige Zeile, wie Sie sie in einem Texteditor finden würden. Die letzte Zeile ist aus Gründen der Lesbarkeit wieder eigenständig. Sie können alle diese eine Zeile machen, wenn nötig. Arbeitet mit Debian Jessie, als ich es getestet habe. 

0
lsu_guy

Echo-Variable in temporäre Textdatei.

Fügen Sie eine Textdatei in mail.tpl ein und löschen Sie data aus mail.tpl

echo ${DATA} > temp.txt    
sed -i -e "/_data_/r temp.txt" -e "//d" mail.tpl
0
Ben Pingilley