web-dev-qa-db-fra.com

Ajout d'une ligne à un fichier uniquement s'il n'existe pas déjà

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

include "/configs/projectname.conf"

dans un fichier nommé lighttpd.conf

Je cherche à utiliser sed pour le faire, mais je ne vois pas comment.

Comment pourrais-je seulement l'insérer si la ligne n'existe pas déjà?

125
Benjamin Dell

Restez simple :)

grep + écho devrait suffire:

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

Edit: suggestions @cerin et @ thijs-wouters incorporées.

230
drAlberT

Ce serait une solution propre, lisible et réutilisable utilisant grep et echo pour ajouter une ligne à un fichier uniquement s'il n'existe pas déjà:

LINE='include "/configs/projectname.conf"'
FILE='lighttpd.conf'
grep -qF -- "$LINE" "$FILE" || echo "$LINE" >> "$FILE"
66
rubo77

Voici une version sed:

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
12
Dennis Williamson

Si vous écrivez dans un fichier protégé, les réponses de @drAlberT et @ rubo77 risquent de ne pas fonctionner, car vous ne pouvez pas utiliser Sudo >>. Une solution simple similaire serait alors d'utiliser tee --append:

LINE='include "/configs/projectname.conf"'
FILE=lighttpd.conf
grep -qF "$LINE" "$FILE"  || echo "$LINE" | Sudo tee --append "$FILE"
7
hamx0r

Si, un jour, quelqu'un d'autre doit traiter ce code en tant que "code hérité", il vous sera reconnaissant si vous écrivez un code moins exotérique, tel que

grep -q -F 'include "/configs/projectname.conf"' lighttpd.conf
if [ $? -ne 0 ]; then
  echo 'include "/configs/projectname.conf"' >> lighttpd.conf
fi
6
Marcelo Ventura

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

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

"Correctement échappé" signifie mettre une expression rationnelle qui correspond à votre entrée, c’est-à-dire échapper à tous les contrôleurs d’expression rationnelle de votre entrée actuall, c’est-à-dire mettre une barre oblique inverse devant ^ ^//?? + ().

cela pourrait échouer sur la dernière ligne de votre fichier ou s'il n'y a pas de nouvelle ligne enchevêtrée, je n'en suis pas sûre, mais cela pourrait être traité par une branche astucieuse ...

5
Robin479

utiliser awk

awk 'FNR==NR && /configs.*projectname\.conf/{f=1;next}f==0;END{ if(!f) { print "your line"}} ' file file
3
ghostdog74

Les réponses utilisant grep sont fausses. Vous devez ajouter une option -x pour faire correspondre toute la ligne, sinon des lignes telles que #text to add sera toujours identique lorsque vous voudrez ajouter exactement text to add.

Donc, la solution correcte est quelque chose comme:

grep -qxF 'include "/configs/projectname.conf"' foo.bar || echo 'include "/configs/projectname.conf"' >> foo.bar
1
Thijs Wouters

tilisation de sed: Il sera inséré en fin de ligne. Vous pouvez également passer des variables comme d’habitude.

grep -qxF "port=9033" $light.conf
if [ $? -ne 0 ]; then
  sed -i "$ a port=9033" $light.conf
else
    echo "port=9033 already added"
fi

tilisation de oneliner sed

grep -qxF "port=9033" $lightconf || sed -i "$ a port=9033" $lightconf

tiliser echo peut ne pas fonctionner sous la racine, mais fonctionnera comme ceci. Mais il ne vous laissera pas automatiser les choses si vous cherchez à le faire car il pourrait vous demander un mot de passe.

J'ai eu un problème lorsque j'essayais de modifier à partir de la racine pour un utilisateur particulier. Il suffit d'ajouter le $username avant était un correctif pour moi.

grep -qxF "port=9033" light.conf
if [ $? -ne 0 ]; then
  Sudo -u $user_name echo "port=9033" >> light.conf
else
    echo "already there"    
fi
1
Rakib Fiha

J'avais besoin d'éditer un fichier avec des autorisations d'écriture restreintes, donc j'avais besoin de Sudo. travaillant avec la réponse de ghostdog74 et utilisant un fichier temporaire:

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
webdevguy