Opérateurs logiques simples dans Bash

J’ai un couple de variables et je veux vérifier la condition suivante (écrit en mots, puis ma tentative infructueuse 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, j’ai trouvé:

 if (($varA == 1)) && ( (($varB == "t1")) || (($varC == "t2")) ); then scale=0.05 fi 

    Ce que vous avez écrit fonctionne en fait presque (cela fonctionnerait si toutes les variables étaient des nombres), mais ce n’est pas du tout une manière idiomatique.

    • (…) parenthèses indiquent un sous – shell . Ce qui est à l’intérieur d’eux n’est pas une expression comme dans beaucoup d’autres langues. C’est une liste de commandes (comme pour les parenthèses extérieures). Ces commandes sont exécutées dans un sous-processus distinct, de sorte que toute redirection, affectation, etc. effectuée à l’intérieur des parenthèses n’a aucun effet en dehors des parenthèses.
      • Avec un signe de dollar en tête, $(…) est une substitution de commande : il y a une commande entre parenthèses et la sortie de la commande est utilisée dans la ligne de commande (après des extensions supplémentaires sauf si la substitution est entre guillemets, mais c’est une autre histoire ).
    • { … } accolades sont comme des parenthèses en ce sens qu’elles regroupent les commandes, mais elles n’influencent que l’parsing, pas le regroupement. Le programme x=2; { x=4; }; echo $x x=2; { x=4; }; echo $x x=2; { x=4; }; echo $x imprime 4, alors que x=2; (x=4); echo $x x=2; (x=4); echo $x x=2; (x=4); echo $x imprime 2. (De même, les accolades exigent des espaces et un point-virgule avant la fermeture, tandis que les parenthèses ne le font pas.
      • Avec un signe de dollar en tête, ${VAR} est une extension de paramètre , élargissant à la valeur d’une variable, avec des transformations supplémentaires possibles.
    • ((…)) doubles parenthèses entourent une instruction arithmétique , c’est-à-dire un calcul sur des entiers, avec une syntaxe ressemblant à d’autres langages de programmation. Cette syntaxe est principalement utilisée pour les affectations et les conditions.
      • La même syntaxe est utilisée dans les expressions arithmétiques $((…)) , qui s’étendent à la valeur entière de l’expression.
    • [[ … ]] doubles crochets entourent les expressions conditionnelles . Les expressions conditionnelles sont principalement construites sur des opérateurs tels que -n $variable pour tester si une variable est vide et -e $file pour tester si un fichier existe. Il y a aussi des opérateurs d’égalité de chaînes: "$ssortingng1" = "$ssortingng2" (attention, le côté droit est un pattern, par exemple [[ $foo = a* ]] teste si $foo commence par a while [[ $foo = "a*" ]] teste si $foo est exactement a* ), et le familier ! , && et || les opérateurs pour la négation, la conjonction et la disjonction, ainsi que les parenthèses pour le regroupement. Notez que vous avez besoin d’un espace autour de chaque opérateur (par exemple [[ "$x" = "$y" ]] , pas [[ "$x"="$y" ]] ), et un espace ou un caractère comme ; à la fois à l’intérieur et à l’extérieur des parenthèses (par exemple [[ -n $foo ]] , pas [[-n $foo]] ).
    • [ … ] parenthèses simples sont une forme alternative d’expressions conditionnelles avec plus de bizarreries (mais plus anciennes et plus portables). N’écrivez pas pour l’instant Commencez à vous en soucier lorsque vous trouvez des scripts qui les contiennent.

    C’est la manière idiomatique d’écrire votre test en bash:

     if [[ $varA = 1 && ($varB = "t1" || $varC = "t2") ]]; then 

    Si vous avez besoin de la portabilité vers d’autres shells, ce serait le cas (notez les citations supplémentaires et les ensembles de crochets séparés autour de chaque test individuel):

     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.

    le décomposer

     [[ $varA -eq 1 ]] 

    est une comparaison d’entier où

     $varB == 't1' 

    est une comparaison de chaîne. sinon, je ne fais que regrouper les comparaisons correctement.

    Les doubles crochets délimitent une expression conditionnelle. Et, je trouve que ce qui suit est une bonne lecture sur le sujet: “(IBM) Demystify test, [, [[, ((et, if-then-else)

    Une version très portable (même pour l’inheritance bourne shell):

     if [ "$varA" = 1 -a \( "$varB" = "t1" -o "$varB" = "t2" \) ] then do-something fi 

    Cela a la qualité supplémentaire d’exécuter un seul sous-processus au maximum (qui est le processus [[]), quelle que soit la saveur du shell.

    Remplacez “=” par “-eq” si les variables contiennent des valeurs numériques, par exemple

    • 3 -eq 03 est vrai, mais
    • 3 = 03 est faux. (comparaison de chaîne)
     if ([ $NUM1 == 1 ] || [ $NUM2 == 1 ]) && [ -z "$STR" ] then echo STR is empty but should have a value. fi 

    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:

    1. || et les opérandes && intérieur si condition (c’est-à-dire entre parenthèses) sont des opérandes logiques (ou / et)

    2. || et && opérandes à l’extérieur si la condition signifie alors / autrement

    Pratiquement, la déclaration dit:

    si (a = 1 ou b = 2) alors “ok” sinon “nok”