bash -e quitte quand let ou expr est évalué à 0

Jai un script bash qui définit -e donc le script se terminera à nimporte quel état de sortie! = 0 .

Jessaye de faire de larithmétique basique du shell assignée aux variables et parfois lexpression est égale à 0, ce qui fait que le statut de sortie de la commande let ou expr est « 1 ».

Voici un exemple:

#!/bin/bash -ex echo "Test 1" Z=`expr 1 - 1` || true echo "Z will print" let "A=4 - 4" echo "A WILL NEVER PRINT $A" Y=`expr 1 - 1` echo "Y WILL NEVER PRINT $Y" X=$(expr 2 - 2) echo "X WILL NEVER PRINT $X" 

Le résultat est:

$ ./test_error.sh + echo "Test 1" Test 1 ++ expr 1 - 1 + Z=0 + true + echo "Z will print" Z will print + let "A=4 - 4" 

Mon La question est de savoir quelle est la manière idiomatique de script bash pour permettre au script déchouer sur des erreurs de sortie réelles et non sur des erreurs arithmétiques de base égalant 0. Je pourrais suffixer toutes ces expressions avec:

A=`expr $C - $D` || true 

Mais cela semble piraté.

Réponse

Nutilisez pas expr pour larithmétique. Elle est obsolète depuis longtemps: les shells ont maintenant larithmétique intégrée, avec la construction $((…)) (POSIX), ou avec let builtin (ksh / bash / zsh) ou la construction ((…)) (ksh / bash / zsh).

let et ((…)) renvoie 1 (un code détat déchec) si la dernière expression évaluée est 0. Pour éviter que cela ne provoque la fermeture de votre script sous set -e, organisez le dernière expression à ne pas renvoyer 0, par exemple:

let "a = 2 - 2" 1 ((a = 2 - 2, 1)) 

Vous pouvez également utiliser lidiome || true:

((a = 2 - 2)) || true 

Sinon, faites votre calcul à lintérieur de $((…)) et vos devoirs à lextérieur. Une affectation renvoie le statut de la dernière substitution de commande dans la valeur, ou 0 sil ny a pas de substitution de commande, vous êtes donc en sécurité. Cela présente lavantage supplémentaire de travailler dans nimporte quel shell POSIX (comme le tiret).

a=$((2 - 2)) 

Réponse

Javais le même problème . tl; dr:

Si le dernier ARG [de let] est évalué à 0, let renvoie 1; let renvoie 0 sinon .

Réponse

Utilisez $(( $C - $D )) à la place pour votre calcul. Cest plus efficace aussi.

Commentaires

  • Quest-ce qui le rend plus efficace que de dire (( A = $C - $D ))?

Réponse

Cette syntaxe fonctionne pour moi:

a=$((b + c)) 

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *