J'ai quelques variables et je veux vérifier la condition suivante (écrite en mots, puis ma tentative ratée de script bash):
if varA EQUALS 1 AND ( varB EQUALS "t1" OR varB EQUALS "t2" ) then
do something
done.
Et dans ma tentative ratée, je suis venu avec:
if (($varA == 1)) && ( (($varB == "t1")) || (($varC == "t2")) );
then
scale=0.05
fi
Ce que vous avez écrit fonctionne presque (cela fonctionnerait si toutes les variables étaient des nombres), mais ce n’est pas du tout une façon idiomatique.
(…)
les parenthèses indiquent un sous-shell . Ce qu’ils contiennent n’est pas une expression comme dans beaucoup d’autres langues. C'est une liste de commandes (tout comme entre parenthèses). Ces commandes étant exécutées dans un sous-processus distinct, toute redirection, affectation, etc. effectuée à l'intérieur des parenthèses n'a aucun effet en dehors des parenthèses. $(…)
est un substitution de commande : il y a une commande à l'intérieur des parenthèses et la sortie de la commande est utilisée dans le cadre de la ligne de commande (après des extensions supplémentaires sauf si la substitution se fait entre guillemets, mais c'est ne autre histoire ).{ … }
ressemblent aux parenthèses dans la mesure où elles regroupent les commandes, mais elles n'influencent que l'analyse, pas le regroupement. Le programme x=2; { x=4; }; echo $x
imprime 4, alors que x=2; (x=4); echo $x
imprime 2. (Les accolades nécessitent également des espaces et un point-virgule avant de se fermer, contrairement aux parenthèses. Ce n'est qu'un caprice de la syntaxe.) ${VAR}
est un extension de paramètre , élargissant la valeur d'une variable, avec des transformations supplémentaires possibles.((…))
deux doubles parenthèses entourent un instruction arithmétique , c'est-à-dire un calcul sur des entiers, avec une syntaxe semblable à celle d'autres langages de programmation. Cette syntaxe est principalement utilisée pour les assignations et dans les conditionnelles. $((…))
, qui se développent à la valeur entière de l'expression.[[ … ]]
doubles crochets entourent expressions conditionnelles . Les expressions conditionnelles sont principalement construites sur opérateurs , tels que -n $variable
pour tester si une variable est vide et -e $file
pour tester si un fichier existe. Il existe également des opérateurs d'égalité des chaînes: "$string1" = "$string2"
(sachez que le côté droit est un motif, par exemple [[ $foo = a* ]]
teste si $foo
commence par a
tandis que [[ $foo = "a*" ]]
teste si $foo
est exactement a*
), ainsi que les opérateurs !
, &&
et ||
bien connus pour la négation, la conjonction et la disjonction, ainsi que les parenthèses pour le groupement. Notez que vous avez besoin d’un espace autour de chaque opérateur (par exemple, [[ "$x" = "$y" ]]
, et non [[ "$x"="$y" ]]
;
à l'intérieur et à l'extérieur des crochets (par exemple, [[ -n $foo ]]
, pas [[-n $foo]]
[ … ]
les parenthèses simples sont une forme alternative d'expressions conditionnelles avec plus de bizarreries (mais plus anciennes et plus portables). N'écris rien pour l'instant. commencez à vous inquiéter à leur sujet lorsque vous trouvez des scripts qui les contiennent.C'est la façon idiomatique d'écrire votre test en bash:
if [[ $varA = 1 && ($varB = "t1" || $varC = "t2") ]]; then
Si vous avez besoin de la transférabilité avec d'autres coques, ce serait la solution (notez la citation supplémentaire et les ensembles de crochets séparés autour de chaque test):
if [ "$varA" = 1 ] && { [ "$varB" = "t1" ] || [ "$varC" = "t2" ]; }; then
très proche
if [[ $varA -eq 1 ]] && [[ $varB == 't1' || $varC == 't2' ]];
then
scale=0.05
fi
devrait marcher.
décomposer
[[ $varA -eq 1 ]]
est une comparaison entière où
$varB == 't1'
est une comparaison de chaîne. sinon, je ne fais que regrouper correctement les comparaisons.
Les doubles crochets délimitent une expression conditionnelle. Et, je trouve que ce qui suit est une bonne lecture sur le sujet: "(IBM) Test de Demystify, [ [[ ((, et si-alors-sinon")
Une version très portable (même pour Legacy Bourne):
if [ "$varA" = 1 -a \( "$varB" = "t1" -o "$varB" = "t2" \) ]
then do-something
fi
Cela présente la qualité supplémentaire de n'exécuter qu'un seul sous-processus (processus '['), quelle que soit la saveur de Shell.
Remplacez "=" par "-eq" si les variables contiennent des valeurs numériques, par ex.
Voici le code de la version courte de l'instruction if-then-else:
( [ $a -eq 1 ] || [ $b -eq 2 ] ) && echo "ok" || echo "nok"
Faites attention à ce qui suit:
||
et &&
opérandes à l'intérieur de la condition si (c'est-à-dire entre parenthèses arrondies) sont des opérandes logiques (ou/et)
||
et &&
opérandes extérieurs si condition signifie alors/autre
Pratiquement la déclaration dit:
si (a = 1 ou b = 2) alors "ok" sinon "nok"
if ([ $NUM1 == 1 ] || [ $NUM2 == 1 ]) && [ -z "$STR" ]
then
echo STR is empty but should have a value.
fi