Ajouter une ligne à un fichier seulement si elle n'existe pas déjà

j'ai besoin d'ajouter la ligne suivante à la fin d'un fichier de configuration:

include "/configs/projectname.conf"

à un fichier appelé lighttpd.conf

je cherche à utiliser sed pour faire ceci, mais je ne peux pas trouver comment.

comment l'insérer seulement si la ligne n'existe pas déjà?

95
demandé sur nbro 2010-08-24 17:40:18

8 réponses

Juste garder les choses simples :)

grep + echo devrait suffire:

grep -q -F 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar

Edit: incorporated @ Cerin suggestion .

NOTE : pour" éditeurs " changer ma réponse: si vous avez une solution alternative donner votre propre réponse! L'édition est destinée à clarifier, formater, mieux l'anglais, et ainsi de suite! Ne changez pas la réponse des autres! (merci)

183
répondu drAlberT 2016-07-22 15:37:49

ce serait une solution propre, lisible et réutilisable utilisant grep et echo pour ajouter une ligne à un fichier seulement si elle n'existe pas déjà:

LINE='include "/configs/projectname.conf"'
FILE=lighttpd.conf
grep -qF -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE"
46
répondu rubo77 2018-02-07 01:03:46

Voici une sed version:

sed -e '\|include "/configs/projectname.conf"|h; ${x;s/incl//;{g;t};a\' -e 'include "/configs/projectname.conf"' -e '}' file

si votre chaîne est dans une variable:

string='include "/configs/projectname.conf"'
sed -e "\|$string|h; ${x;s|$string||;{g;t};a\" -e "$string" -e "}" file
11
répondu Dennis Williamson 2010-08-24 19:04:50

si vous écrivez à un fichier protégé, les réponses de @drAlberT et @rubo77 pourraient ne pas fonctionner pour vous puisqu'on ne peut pas sudo >> . Une Solution tout aussi simple , alors, serait d'utiliser tee --append :

LINE='include "/configs/projectname.conf"'
FILE=lighttpd.conf
grep -qF "$LINE" "$FILE"  || echo "$LINE" | sudo tee --append "$FILE"
6
répondu hamx0r 2017-05-23 11:47:16

utiliser awk

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file file
3
répondu ghostdog74 2010-08-24 14:05:22

une autre solution sed consiste à toujours l'ajouter à la dernière ligne et supprimer une ligne préexistante.

sed -e '$a\' -e '<your-entry>' -e "/<your-entry-properly-escaped>/d"

"correctement échappé" signifie mettre un regex qui correspond à votre entrée, c.-à-d. pour échapper à tous les contrôles regex de votre entrée actuelle, c.-à-d. pour mettre un infront antislash de ^$/*?+().

cela pourrait échouer sur la dernière ligne de votre dossier ou s'il n'y a pas de newline emmêlant, Je ne suis pas sûr, mais cela pourrait être réglé par une branche chic...

3
répondu Robin479 2014-05-08 18:16:43

si, un jour, quelqu'un d'autre a pour traiter avec ce code comme "code d'héritage", alors cette personne sera reconnaissante si vous écrivez un code moins exotérique, comme

grep -q -F 'include "/configs/projectname.conf"' lighttpd.conf
if [ $? -ne 0 ]; then
  echo 'include "/configs/projectname.conf"' >> lighttpd.conf
fi
2
répondu Marcelo Ventura 2018-08-30 12:43:01

j'ai eu besoin d'éditer un fichier avec des permissions d'écriture limitées si nécessaire sudo . travaillant à partir de la réponse de ghostdog74 et en utilisant un fichier temp:

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file > /tmp/file
sudo mv /tmp/file file
0
répondu webdevguy 2014-04-29 14:44:47