web-dev-qa-db-fra.com

Opérateurs logiques simples dans Bash

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
219
Amit

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.
    • Avec un signe dollar en avance, $(…) 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 ).
  • Les accolades { … } 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.)
    • Avec le signe dollar en tête, ${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.
    • La même syntaxe est utilisée dans les expressions arithmétiques $((…)), 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" ]]) et un espace ou un caractère tel que ; à 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
602
Gilles

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")

33
matchew

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.

  • 3 -eq 03 est vrai, mais
  • 3 = 03 est faux. (comparaison de chaîne)
6
J.P. Tosoni

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 && opérandes à l'intérieur de la condition si (c'est-à-dire entre parenthèses arrondies) sont des opérandes logiques (ou/et)

  2. || 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"

2
tlc
if ([ $NUM1 == 1 ] || [ $NUM2 == 1 ]) && [ -z "$STR" ]
then
    echo STR is empty but should have a value.
fi
0
AlikElzin-kilaka