Comment ajouter une ligne dans sed si pas de correspondance est trouvée
Je suis en utilisant le suivant sed
commande pour remplacer certains paramètres dans un fichier de config:
sed -i 's/^option.*/option=value/g' /etc/fdm_monitor.conf
Maintenant, j'ai un problème. Si la ligne n'existe pas, je veux l'ajouter à la fin du fichier.
Je suis à l'appel de cette avec un popen
d'un programme C. J'ai essayé d'utiliser awk
.
Vous devez vous connecter pour publier un commentaire.
Essayez ceci:
À l'aide de sed, la syntaxe est simple:
Ce serait de remplacer le paramètre s'il existe, d'autre serait-il ajouter à la fin du fichier.
Utiliser le
-i
option si vous souhaitez modifier le fichier en place.Si vous voulez accepter et de respecter les espaces blancs, et en plus de supprimer le commentaire, si la ligne existe déjà, mais est commenté, écrire:
Veuillez noter que ni option ni la valeur doit contenir une barre oblique
/
, ou vous aurez à échapper à\/
.À utiliser bash-variables
$option
et$value
, vous pourriez écrire:Le bash expression
${option//\//\\/}
citations des barres obliques, il remplace toutes les/
avec\/
.Remarque: j'ai Juste pris au piège dans un problème. En bash, vous pouvez citer des
"${option//\//\\/}"
, mais dans le sh de busybox, cela ne fonctionne pas, alors vous devriez éviter les guillemets, au moins dans la non-bourne-coques.Tous intégrés dans une fonction bash:
Explication:
/^\(option=\).*/
: Match lignes qui commencent paroption=
et (.*
) ignorer tout ce qui est après le=
. Le\(
...\)
entoure la partie, nous allons réutiliser comme\1
plus tard.#
au début de la ligne.\?
signifie «facultatif». Le commentaire sera supprimé, car il est à l'extérieur de la copie d'une partie de\(
...\)
.\s*
signifie «un nombre quelconque d'espaces blancs» (espace, tabulation). Les espaces blancs sont copiés, car ils sont à l'intérieur de\(
...\)
, afin de ne pas perdre la mise en forme./^\(option=\).*/{…}
: Si correspond à une ligne de/…/
, puis exécutez la commande suivante. Commande à exécuter n'est pas une commande, mais un bloc de{…}
.s//…/
: Rechercher et remplacer. Depuis le terme de recherche est vide//
, il s'applique pour le dernier match, qui a été/^\(option=\).*/
.s//\1value/: Replace the last match with everything in
(...), referenced by
\1and the text
valeur":a;n;ba;q
: Définir l'étiquettea
, alors lisez la ligne suivanten
, puis la brancheb
(ou goto) retour à l'étiquettea
, ce qui signifie: lire toutes les lignes jusqu'à la et de fichier, donc après le premier match, juste extraire toutes les lignes suivantes, sans autre traitement. Puisq
guit et donc ignorer tout le reste.$aoption=value
: À la fin du fichier$
, ajoutera
le texteoption=value
Plus d'informations sur
sed
et une commande de présentation est sur mon blog:sed
code./
personnage en utilisant un autre personnage dans la commande de substitution (comme!
):sed -i -e '/^\(option=\).*/{s!!\1value!;:a;n;ba;q}' -e '$aoption=value' filename
sed 's,from,to,g'
, mais pour permettre l'arbitraire paires nom / valeur, par exemple, les arguments d'un appel de fonction, vous avez encore besoin de leur échapper.Comme awk-un seul-liner:
ARGV[1] est votre entrée
file
. Il est ouvert à l'écrit dans lefor
boucle de laEND
bloc. Ouverturefile
pour la sortie dans leEND
bloc remplace le besoin pour les services publics, commesponge
ou l'écriture dans un fichier temporaire, puismv
ing le fichier temporaire pourfile
.Les deux affectations à la matrice
a[]
accumuler toutes les lignes de sortie ena
.if(!f)a[++n]=s
ajoute le nouveauoption=value
si le principal awk boucle ne pouvais pas trouveroption
dansfile
.J'ai ajouté des espaces (pas beaucoup) pour des raisons de lisibilité, mais vous avez vraiment besoin d'un lieu dans l'ensemble du programme awk, l'espace après
print
.Si
file
comprend# comments
ils seront préservés.Ici est un one-liner sed qui fait le travail en ligne. Notez que il préserve l'emplacement de la variable et sa mise en retrait dans le fichier s'il existe. C'est souvent important pour le contexte, comme quand il y a des commentaires ou lorsque la variable est dans un bloc indenté. Toute solution fondée sur "supprimer puis ajouter" paradigme d'échec de mal à cela.
Avec un générique paire de variable/valeur que vous pouvez l'écrire de cette façon:
Enfin, si vous voulez aussi garder les commentaires en ligne, vous pouvez le faire avec une prise de groupe. E. g. si
test.conf
contient les éléments suivants:Puis exécuter ce
Produit:
voici un awk one-liner:
ce n'est pas faire place au changement sur le fichier, vous pouvez cependant :
À l'aide de
sed
, vous pourriez dire:Ce serait de remplacer le paramètre s'il existe, d'autre serait-il ajouter à la fin du fichier.
Utiliser le
-i
option si vous souhaitez modifier le fichier en place:Voici un
awk
mise en œuvreL'exécuter à l'aide de
ou
EDIT:
Comme un one-liner:
Charger tout le fichier en mémoire tampon, à la fin, de modifier toutes les occurrences et si pas de changement, ajouter à la fin
J'ai élaboré sur kev du grep/sed solution en définissant des variables afin de réduire les chevauchements.
Définir les variables dans la première ligne (indice:
$_option
doit correspondre à tout pour le tout, jusqu'à la valeur de [y compris tout élément de séparation comme = ou :]).L'esprit que le
sh -c '...'
a juste l'effet de l'élargissement de la portée des variables sans avoir besoin d'unexport
. (Voir Définition d'une variable d'environnement avant une commande de bash ne fonctionne pas pour la deuxième commande dans un tuyau)Vous pouvez utiliser cette fonction pour rechercher et de recherche de modifications de configuration: