48 votes

sed : comment remplacer une ligne si elle est trouvée ou l'ajouter à la fin du fichier si elle n'est pas trouvée ?

Avec un seul fichier d'entrée qui ne contient que des commentaires (commençant par #) et des lignes VARIABLE=valeur, est-il possible de remplacer une valeur pour une seule variable si elle est trouvée et, dans le cas contraire, d'ajouter la paire à la fin du fichier si elle n'est pas trouvée ?

Ma méthode actuelle consiste à l'effacer dans un premier temps, puis à l'ajouter à la fin du fichier dans un second temps, mais cette méthode perturbe l'ordre des lignes (et il s'agit également de deux commandes différentes) :

sed -r "/^FOOBAR=.*$/d"      -i samefile &&
sed -r "$ a\FOOBAR=newvalue" -i samefile

Existe-t-il un moyen de faire cela, c'est-à-dire de conserver l'ordre des lignes, en une seule ligne sed ? Si un autre utilitaire (awk, ...) fait cela, je le préférerais à sed.

46voto

don_crissti Points 2644

C'est en fait assez simple avec sed Si une ligne correspond, il suffit de la copier dans le fichier h ancien espace alors s ubstituer la valeur.
Sur la la $ t ligne e x changer l'espace de maintien et l'espace de motif, puis vérifier si ce dernier est vide. S'il n'est pas vide, cela signifie que la substitution a déjà été effectuée et qu'il n'y a donc rien à faire. S'il est vide, cela signifie qu'aucune correspondance n'a été trouvée et qu'il faut donc remplacer l'espace de motif par la valeur souhaitée. variable=valeur puis l'ajouter à la ligne actuelle dans le tampon de maintien. Enfin, e x changer à nouveau :

sed '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile

Ce qui précède est gnu sed syntaxe. Portable :

sed '/^FOOBAR=/{
h
s/=.*/=newvalue/
}
${
x
/^$/{
s//FOOBAR=newvalue/
H
}
x
}' infile

31voto

haridsv Points 569

Voici un exemple plus simple sed car je ne trouve pas que l'approche de la sed hold space facile à travailler. Si vous êtes à l'aise avec hold space L'utilisation de l'approche don_crissti offre une possibilité supplémentaire de préserver quoi que ce soit de la ligne existante, mais cela est généralement très rare.

Dans cette approche, il suffit d'imprimer toute la ligne sauf celle que l'on veut supprimer, puis d'ajouter le texte de remplacement à la fin.

sed -n -e '/^FOOBAR=/!p' -e '$aFOOBAR=newvalue' infile

19voto

Kurt Pattyn Points 1650

Il est probablement possible d'abréger ce point. Ce n'est pas une simple commande sed et elle utilise aussi grep, mais cela semble être essentiellement ce que vous voulez. Il s'agit d'une seule ligne, et le fichier est modifié sur place (pas de fichiers temporaires).

grep -q "^FOOBAR=" file && sed "s/^FOOBAR=.*/FOOBAR=newvalue/" -i file || 
    sed "$ a\FOOBAR=newvalue" -i file

4voto

MUY Belgium Points 325

Il suffit d'utiliser grep y echo pour créer un enregistrement vide :

grep -q '^FOOBAR=' somefile || echo 'FOOBAR=VALUE' >> somefile
sed -i 's/FOOBAR=.*$/FOOBAR=VALUE/' somefile 

Chaque ligne s'échappe avec le code d'erreur zéro.

2voto

Mohsin Points 11

D'après les autres réponses, si ce que vous voulez faire est de remplacer la valeur d'une variable si cette variable est présente dans le fichier et de l'ajouter à la fin du fichier si elle ne l'est pas (ce qui n'est pas ce que vous avez indiqué dans votre message), il est possible de remplacer la valeur d'une variable si elle est présente dans le fichier. sed ), vous pouvez essayer ceci :

perl -ne '$c=1 if s/^FOOBAR=.*$/FOOBAR=newvalue/;  
             print; 
             END{print "FOOBAR=newvalue" unless $c==1}' file > tmpfile && 
mv tmpfile file

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X