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!)
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
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
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.
Je suggérerais simplement de remplacer sed avec la commande Perl comme ceci:
Perl -i.bak -pe 's/_data_/'"${DATA}"'/g' mail.tpl
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.
É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
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
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.
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