web-dev-qa-db-fra.com

Remplacer un mot avec plusieurs lignes en utilisant sed?

Je travaille sur un script bash qui doit préparer un courrier électronique en vue de son envoi à un utilisateur.

Il agrège certaines données, ce qui finit par être constitué de plusieurs lignes de données. Pour l'exemple stocké dans $DATA.

Maintenant, après un peu de stfw, j'ai trouvé quelques choses comme sed -ei "s/_data_/${DATA}/g" mail.tpl et aussi sed remplacer par variable avec plusieurs lignes . Aucun d'entre eux ne fonctionne.

Maintenant, la question est de savoir comment je peux obtenir sed pour remplacer quelque chose par plusieurs lignes de texte.

(Les alternatives à sed sont également les bienvenues!)

17
Cobra_Fast

Si vous construisez votre texte de plusieurs lignes avec "\n", cela fonctionnera avec une simple commande sed en tant que:

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

Je l'ai essayé et sed 's/pattern/\na\nb\nc/g' mais cela ne fonctionne pas sur tous les systèmes. Quel est le travail met un \ suivi d'une nouvelle ligne dans le modèle de remplacement, comme ceci:

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

Ceci ajoute une ligne contenant b et une ligne contenant c lorsque le motif est vu.

Pour le mettre dans une variable, utilisez des doubles barres obliques inverses:

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

et alors:

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

Notez les guillemets doubles.

9
Albert Veli

Je suggérerais simplement de remplacer sed avec la commande Perl comme ceci:

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

la réponse du porteur de bague n'a pas fonctionné pour moi; Je pense que l'utilisation de tr ici est fausse et que, dans son libellé actuel, elle supprime simplement les nouvelles lignes en utilisant echo.

Au lieu de cela, j'ai utilisé sed. J'ai utilisé le code de une autre réponse pour remplacer les nouvelles lignes (crédit: Zsolt Botykai). Je m'attendais aussi à des signes de dollar ($) dans mon entrée, donc je m'en suis occupé aussi. Vous devrez peut-être ajouter une autre gestion des entrées. Notez l'utilisation de guillemets doubles dans echo pour préserver les retours à la ligne.

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

Ensuite, vous pouvez utiliser ${ESCAPED_DATA} dans sed:

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

Je pensais juste partager.

7
Yuval

Échapper à toutes les nouvelles lignes avec un \ (sauf le dernier) a fonctionné pour moi. La dernière nouvelle ligne ne doit pas être échappée pour ne pas interrompre la commande s.

Exemple :

DATA="a
b
c"

ESCAPED=$(echo "${DATA}" | sed '$!s@$@\\@g')
echo "${ESCAPED}" 
a\
b\
c

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

Vous pouvez mettre vos données dans un fichier temporaire et exécuter:

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

Pas sûr si vous avez essayé de mettre "\ n" dans la pièce à remplacer

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

La première ligne a/\ pour des raisons de lisibilité. Chaque ligne suivante est une ligne autonome, comme dans un éditeur de texte. La dernière ligne est autonome, encore une fois pour des raisons de lisibilité. Vous pouvez faire toute cette ligne si nécessaire. Fonctionne sur Debian Jessie lorsque je l’ai testée. 

0
lsu_guy

Echo variable dans un fichier texte temporaire.

Insérer un fichier texte dans mail.tpl et supprimer data from mail.tpl

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