Bash if instruction avec plusieurs conditions lève une erreur

165

J'essaie d'écrire un script qui vérifiera deux indicateurs d'erreur, et au cas où un indicateur (ou les deux) serait modifié, il fera écho - une erreur s'est produite. Mon scénario:

my_error_flag=0
my_error_flag_o=0
do something.....
if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" &&     "$my_error_flag_o"="2" ]]; then
    echo "$my_error_flag"
else
    echo "no flag"
fi

Fondamentalement, cela devrait être quelque chose le long:

if ((a=1 or b=2) or (a=1 and b=2))
  then
     display error
else
     no error
fi

L'erreur que j'obtiens est:

 line 26: conditional binary operator expected
 line 26: syntax error near `]'
 line 26: `if [[ "$my_error_flag"=="1" || "$my_error_flag_o"=="2" ] || [ "$my_error_flag"="1" && "$my_error_flag_o"="2" ]]; then'

Mes supports sont-ils foirés?

Simplement moi
la source
2
Utiliser des parenthèses - ()
AlikElzin-kilaka
3
Logiquement, a==1 or b==2couvre déjà le cas où a==1 and b==2. Tester séparément pour cela est complètement superflu ici.
tripleee le

Réponses:

249

Utilisez les opérations -a(pour et) et -o(pour ou).

tldp.org/LDP/Bash-Beginners-Guide/html/sect_07_01.html

Mettre à jour

En fait, vous pouvez toujours utiliser &&et ||avec l' -eqopération. Donc, votre script serait comme ceci:

my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] ||  [ $my_error_flag_o -eq 2 ] || ([ $my_error_flag -eq 1 ] && [ $my_error_flag_o -eq 2 ]); then
      echo "$my_error_flag"
else
    echo "no flag"
fi

Bien que dans votre cas, vous pouvez supprimer les deux dernières expressions et vous en tenir à une ou à une opération comme celle-ci:

my_error_flag=1
my_error_flag_o=1
if [ $my_error_flag -eq 1 ] ||  [ $my_error_flag_o -eq 2 ]; then
      echo "$my_error_flag"
else
    echo "no flag"
fi
mkhatib
la source
3
@Simply_Me: Non, un OU logique est vrai si l'un de ses opérandes ou les deux sont vrais. Vous pensez à "exclusif ou" (XOR), qui est vrai si exactement l'un de ses opérandes est vrai. (En fait, il existe des versions de XOR qui fonctionnent sur plus de 2 opérandes, auquel cas c'est vrai si un nombre impair d'opérandes est vrai.)
Gordon Davisson
4
BTW, les problèmes dans le code d'origine incluent l'utilisation [et ]pour le regroupement (ils ne le font pas), et le fait de ne pas mettre d'espaces autour de l'opérateur (par exemple "$my_error_flag"="1"), ce qui empêche le shell de le reconnaître comme un opérateur du tout. Veuillez lire BashFAQ # 17 (sur le regroupement) et # 31 (sur la différence entre les différents types d'expression de test) . En fait, dans ce cas, il serait encore plus facile d'utiliser une expression arithmétique .
Gordon Davisson
7
-aet -osont considérés comme obsolètes par la spécification POSIX ; utilisez des tests séparés combinés avec ||comme dans la mise à jour.
chepner
1
Pas besoin de regrouper en utilisant des sous-shell, normalement le regroupement en utilisant {}devrait également être possible.
phk
1
pour ajouter au commentaire de phk ci-dessus, () lance des sous-shell dans bash, qui peuvent avoir toutes sortes d'effets subtils [probablement indésirables].
brett
70

Vous pouvez utiliser l'un [[ou l' autre ((mot - clé. Lorsque vous utilisez [[mot - clé, vous devez les opérateurs de chaîne d'utilisation tels que -eq, -lt. Je pense que ((c'est le plus préféré pour l'arithmétique, car vous pouvez utiliser directement des opérateurs tels que ==, <et >.

Utilisation de l' [[opérateur

a=$1
b=$2
if [[ a -eq 1 || b -eq 2 ]] || [[ a -eq 3 && b -eq 4 ]]
then
     echo "Error"
else
     echo "No Error"
fi

Utilisation de l' ((opérateur

a=$1
b=$2
if (( a == 1 || b == 2 )) || (( a == 3 && b == 4 ))
then
     echo "Error"
else
     echo "No Error"
fi

Ne pas utiliser -ani -oopérateurs car il n'est pas portable.

Fizer Khan
la source
8

Veuillez essayer de suivre

if ([ $dateR -ge 234 ] && [ $dateR -lt 238 ]) || ([ $dateR -ge 834 ] && [ $dateR -lt 838 ]) || ([ $dateR -ge 1434 ] && [ $dateR -lt 1438 ]) || ([ $dateR -ge 2034 ] && [ $dateR -lt 2038 ]) ;
then
    echo "WORKING"
else
    echo "Out of range!"
Manash Nath
la source
2
( ... )crée des sous-couches - beaucoup d'impact sur les performances sans aucun avantage.
Charles Duffy
4
À utiliser { ...; }pour le regroupement sans création de sous-shell.
Charles Duffy
1

Vous pouvez vous inspirer en lisant un entrypoint.sh script écrit par les contributeurs de MySQL qui vérifie si les variables spécifiées ont été définies.

Comme le script le montre, vous pouvez les canaliser avec -a, par exemple:

if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
    ...
fi
Daniel Andrei Mincă
la source
1
-aest marqué comme obsolescent dans la version actuelle du teststandard POSIX ; voir les OBmarqueurs sur pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html . Utilisez [ -z "$FOO" ] && [ -z "$BAR" ]pour avoir un code plus fiable.
Charles Duffy