Avec un seul fichier d'entrée contenant uniquement des commentaires (commençant par #) et des lignes de valeur VARIABLE =, est-il possible de remplacer une valeur pour une seule variable si elle est trouvée et, sinon, d'ajouter la paire à la fin du fichier si elle n'est pas trouvée?
Ma méthode actuelle fonctionne en la supprimant lors d'un premier passage, puis en l'ajoutant à la fin du fichier lors d'un second passage, mais cette méthode perturbe l'ordre des lignes (et comporte également deux commandes différentes):
sed -r "/^FOOBAR=.*$/d" -i samefile &&
sed -r "$ a\FOOBAR=newvalue" -i samefile
Est-il possible de le faire, c.-à-d. garder l'ordre de la ligne, dans une seule ligne sed? Si un autre utilitaire (awk, ...) le fait, je le prendrais en charge.
C'est en fait assez simple avec sed
: si une ligne correspond, copiez-la simplement dans l'espace h
old, puis s
ubstitute la valeur.
Sur la la$
t line ex
changez les espaces de maintien et de motif, puis vérifiez si ce dernier est vide. Si ce n'est pas vide, cela signifie que la substitution a déjà été faite, donc rien à faire. Si elle est vide, cela signifie qu'aucune correspondance n'a été trouvée, alors remplacez l'espace de modèle par la variable désirée = value puis ajoutez-la à la ligne en cours dans le tampon de maintien. Enfin, ex
change à nouveau:
sed '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile
La syntaxe ci-dessus est gnu sed
. Portable:
sed '/^FOOBAR=/{
h
s/=.*/=newvalue/
}
${
x
/^$/{
s//FOOBAR=newvalue/
H
}
x
}' infile
Cela peut probablement être raccourci. Ce n'est pas une seule commande sed et il utilise également grep, mais cela semble être fondamentalement ce que vous voulez. Il s’agit d’une seule ligne et édite le fichier sur place (aucun fichier temporaire).
grep -q "^FOOBAR=" file && sed "s/^FOOBAR=.*/FOOBAR=newvalue/" -i file ||
sed "$ a\FOOBAR=newvalue" -i file
Voici une approche sed
plus simple, car je ne trouve pas sed
hold space
facile à utiliser. Si vous êtes à l'aise avec hold space
, l'utilisation de l'approche don_crissti offre une possibilité supplémentaire de préserver un élément de la ligne existante, mais cela est généralement très rare.
Dans cette approche, il vous suffit d'imprimer toutes les lignes sauf la ligne que vous souhaitez supprimer, puis d'ajouter le remplacement à la fin.
sed -n -e '/^FOOBAR=/!p' -e '$aFOOBAR=newvalue' infile
Sur la base des autres réponses, si vous voulez remplacer la valeur d'une variable si cette variable est présente dans le fichier et l'ajouter à la fin du fichier si ce n'est pas le cas (ce qui n'est pas ce que font vos commandes sed
), vous pouvez essayer ceci:
Perl -ne '$c=1 if s/^FOOBAR=.*$/FOOBAR=newvalue/;
print;
END{print "FOBAR=newvalue" unless $c==1}' file > tmpfile &&
mv tmpfile file
C'est un peu plus simple dans awk, bien que l'édition "sur place" ne soit pas automatique:
awk -v varname="FOOBAR" -v newval="newvalue" '
BEGIN {FS = OFS = "="}
$1 == varname {$2 = newval; found = 1}
{print}
END {if (! found) {print varname, newval}}
' file > tempfile &&
mv tempfile file
Utilisez simplement grep
et 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.
Fonctionne réellement avec ce qui suit: sed -i '/^FOOBAR=/{h;s/=.*/=newvalue/};${x;/^$/{s//FOOBAR=newvalue/;H};x}' infile
Dans la réponse choisie -i est manquant.