J'utilise sed
pour mettre à jour mon fichier de configuration json dans le runtime . Parfois, lorsque le motif ne correspond pas dans le fichier json, sed
quitte toujours avec le code retour 0.
Renvoyer 0 signifie que l'opération a abouti, mais pourquoi sed
renvoie-t-il 0 s'il ne trouve pas le modèle approprié et met à jour le fichier? Y at-il une solution de contournement pour cela?
Merci!
comme @cnicutar a commenté, le code retour d'une commande signifie que la commande a été exécutée avec succès. n'a rien à voir avec la logique que vous avez implémentée dans les codes/scripts.
alors si vous avez:
echo "foo"|sed '/bar/ s/a/b/'
sed retournera 0
mais si vous écrivez des erreurs de syntaxe/expression, ou si le fichier/entrée n'existe pas, sed ne peut pas exécuter votre demande, sed retournera 1.
solution de contournement
ce n'est en fait pas solution de contournement . sed a la commande q
: (depuis la page de manuel):
q [exit-code]
ici, vous pouvez définir le code de sortie que vous voulez. Par exemple, '/foo/!{q100}; {s/f/b/}'
quittera avec le code 100 si foo
n'est pas présent, sinon, effectuez la substitution f-> b et quittez avec le code 0.
Cas assorti:
kent$ echo "foo" | sed '/foo/!{q100}; {s/f/b/}'
boo
kent$ echo $?
0
Cas inégalé:
kent$ echo "trash" | sed '/foo/!{q100}; {s/f/b/}'
trash
kent$ echo $?
100
J'espère que cela répond à votre question.
modifier
Je dois ajouter que l'exemple ci-dessus concerne uniquement le traitement sur une ligne. Je ne connais pas votre exigence exacte. quand vous voulez obtenir exit 1
. une ligne sans correspondance ou le fichier entier. Si le cas de fichier entier ne correspond pas, vous pouvez envisager awk, ou même faire un grep
avant votre traitement de texte ...
Cela pourrait fonctionner pour vous (GNU sed):
sed '/search-string/{s//replacement-string/;h};${x;/./{x;q0};x;q1}' file
Si le search-string
est trouvé, il sera remplacé par replacement-string
et à la fin du fichier, sed
sera fermé avec le code retour 0
. Si aucune substitution n'a lieu, le code de retour sera 1
.
Une explication plus détaillée:
Dans l'utilisateur sed, l'utilisateur dispose de deux registres: l'espace de modèle (PS) dans lequel la ligne actuelle est chargée (moins le saut de ligne) et un registre de réserve appelé espace de maintien (HS) initialement vide.
L'idée générale est d'utiliser le SH comme un indicateur pour indiquer si une substitution a eu lieu. Si le SH est toujours vide à la fin du fichier, aucune modification n'a été apportée, sinon des modifications sont survenues.
La commande /search-string/
établit une correspondance avec search-string
avec tout ce qui se trouve dans le PS. Si elle contient le search-string
, les commandes entre les accolades suivantes sont exécutées.
Premièrement, la substitution s//replacement-string/
(sed utilise la dernière expression rationnelle, c'est-à-dire le search-string
, si le côté gauche est vide, donc s//replacement-string
est identique à s/search-string/replacement-string/
), puis la commande h
crée une copie du PS et la place dans le SH.
La commande sed $
est utilisée pour reconnaître la dernière ligne d'un fichier et les événements suivants se produisent.
Tout d’abord, la commande x
permute les deux registres, de sorte que le SH devient le PS et que le PS devient le HS.
Ensuite, tous les caractères sont recherchés dans le PS. /./
(.
signifie que tous les caractères correspondent). Rappelez-vous que le SH (à présent, le PS) était initialement vide jusqu'à ce qu'une substitution ait eu lieu. Si la condition est vraie, la variable x
est à nouveau exécutée, suivie de la commande q0
qui met fin à tout le traitement sed et définit le code de retour sur 0
. Sinon, la commande x
est exécutée et le code de retour est défini sur 1
.
N.B. bien que la q
abandonne le traitement sed, cela n'empêche pas le PS d'être réassemblé par sed et imprimé comme d'habitude.
Une autre alternative:
sed '/search-string/!ba;s//replacement-string/;h;:a;$!b;p;x;/./Q;Q1' file
ou:
sed '/search-string/,${s//replacement-string/;b};$q1' file
Ces réponses sont trop compliquées. Qu'y a-t-il de mal à écrire un peu de script Shell qui utilise grep pour déterminer si l'élément que vous souhaitez remplacer utilise la méthode sed pour le remplacer?
grep -q $TARGET_STRING $file
if [ $? -eq 0 ]
then
echo "$file contains the old site"
sed -e "s|${TARGET_STRING}|${NEW_STRING}|g" ....
fi
Vous trouverez ci-dessous le modèle que nous utilisons avec sed -rn
ou sed -r
.
La commande de recherche et de remplacement complète ("s/.../.../...") est facultative. Si la recherche et le remplacement sont utilisés, pour des raisons de rapidité et ayant déjà correspondu à $ matchRe, nous utilisons aussi rapidement que possible une valeur $ searchRe, en utilisant. où le caractère n'a pas besoin d'être revérifié et. {$ len} pour les sections de longueur fixe du motif.
La valeur de retour pour no found est $ notFoundExit.
/$matchRe/{s/$searchRe/$replacement/$options; Q}; q$notFoundExit
Pour les raisons suivantes:
En modifiant le cas des commandes Q, le comportement variera en fonction du moment où l'exit doit avoir lieu. Les comportements impliquant l'application de la logique booléenne à une entrée de ligne multiple nécessitent plus de complexité dans la solution.
J'avais voulu tronquer un fichier en quittant quand la correspondance a été trouvée (et exclure la ligne correspondante). C'est pratique lorsqu'un processus qui ajoute des lignes à la fin du fichier peut être réexécuté. "Q; Q1" n'a pas fonctionné, mais simplement "Q1" comme suit:
si sed -i '/ texte je voulais trouver/Q1' fichier.txt puis insérer une ligne blanche à la fin du fichier + nouvelles lignes fi insérer uniquement les nouvelles lignes sans la ligne blanche
Comme nous le savons déjà, lorsque sed ne correspond pas, il renvoie simplement sa chaîne d'entrée - aucune erreur ne s'est produite. Il est vrai qu'une différence entre les chaînes d'entrée et de sortie implique une correspondance, mais une correspondance n'implique pas une différence dans les chaînes; après tout, sed aurait simplement pu faire correspondre tous les caractères saisis . La faille est créée dans l'exemple suivant
h=$(echo "$g" | sed 's/.*\(abc[[:digit:]]\).*/\1/g')
if [ ! "$h" = "$g" ]; then
echo "1"
else
echo "2"
fi
où g=Xabc1
donne 1, alors que g=abc1
donne 2; pourtant, sed est la même chose pour ces deux chaînes d'entrée. Il peut donc être difficile de déterminer si sed est compatible ou non. Une solution:
h=$(echo "fix${g}ed" | sed 's/.*\(abc[[:digit:]]\).*/\1/g')
if [ ! "$h" = "fix${g}ed" ]; then
echo "1"
else
echo "2"
fi
dans ce cas, le 1 est imprimé si et seulement si sed correspond.