Comment représenter des conditions multiples dans une instruction shell if?
je veux représenter plusieurs conditions comme celle-ci:
if [ ( $g -eq 1 -a "$c" = "123" ) -o ( $g -eq 2 -a "$c" = "456" ) ]
then
echo abc;
else
echo efg;
fi
mais quand j'exécute le script, il montre
syntax error at line 15: `[' unexpected,
où la ligne 15 est celui si ....
Qu'est-ce qui ne va pas avec cette condition? Je suppose que quelque chose ne va pas avec le ()
.
6 réponses
technique Classique d'échappement des caractères de remplacement):
if [ \( "$g" -eq 1 -a "$c" = "123" \) -o \( "$g" -eq 2 -a "$c" = "456" \) ]
then echo abc
else echo efg
fi
j'ai joint les références à $g
entre guillemets; c'est une bonne pratique, en général. Strictement, les parenthèses ne sont pas nécessaires parce que la préséance de -a
et -o
le rend correct même sans eux.
notez que les opérateurs -a
et -o
font partie de la spécification POSIX pour test
, alias [
, principalement pour la rétrocompatibilité (puisqu'ils faisaient partie de test
dans la 7ème édition D'UNIX, par exemple), mais ils sont explicitement marqués comme "obsolescents" par POSIX. Bash (voir expressions conditionnelles ) semble préférer les significations classique et POSIX pour -a
et -o
avec ses propres opérateurs alternatifs qui prennent des arguments.
avec un certain soin, vous pouvez utiliser le plus moderne [[
opérateur, mais être conscient que les versions dans Bash et Korn Shell (par exemple) n'ont pas besoin d'être identiques.
for g in 1 2 3
do
for c in 123 456 789
do
if [[ ( "$g" -eq 1 && "$c" = "123" ) || ( "$g" -eq 2 && "$c" = "456" ) ]]
then echo "g = $g; c = $c; true"
else echo "g = $g; c = $c; false"
fi
done
done
exemple d'exécution, en utilisant Bash 3.2.57 sur Mac OS X:
g = 1; c = 123; true
g = 1; c = 456; false
g = 1; c = 789; false
g = 2; c = 123; false
g = 2; c = 456; true
g = 2; c = 789; false
g = 3; c = 123; false
g = 3; c = 456; false
g = 3; c = 789; false
vous n'avez pas besoin de citer les variables dans [[
comme vous le faites avec [
parce que ce n'est pas une commande séparée de la même manière que [
est.
N'est-ce pas une question classique?
je l'aurais pensé. Toutefois, il existe une autre solution, à savoir:
if [ "$g" -eq 1 -a "$c" = "123" ] || [ "$g" -eq 2 -a "$c" = "456" ]
then echo abc
else echo efg
fi
en Effet, si vous lisez le "portable shell" lignes directrices pour la autoconf
de l'outil ou de paquets, cette notation en utilisant " ||
" et " &&
' - est ce qu'ils recommandent. Je suppose que vous pourriez même aller jusqu'à:
if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi
où les actions sont aussi insignifiantes que en écho, ce n'est pas mauvais. Lorsque le bloc d'action à répéter est composé de plusieurs lignes, la répétition est trop douloureuse et l'une des versions précédentes est préférable - ou vous devez envelopper les actions dans une fonction qui est invoquée dans les différents blocs then
.
Dans Bash:
if [[ ( $g == 1 && $c == 123 ) || ( $g == 2 && $c == 456 ) ]]
par /bin/bash
, on entend:
if [ "$option" = "Y" ] || [ "$option" = "y" ]; then
echo "Entered $option"
fi
$ g=3
$ c=133
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg"
efg
$ g=1
$ c=123
$ ([ "$g$c" = "1123" ] || [ "$g$c" = "2456" ]) && echo "abc" || echo "efg"
abc
soyez prudent si vous avez des espaces dans vos variables string et vous vérifiez l'existence. Assurez-vous de les citer correctement.
if [ ! "${somepath}" ] || [ ! "${otherstring}" ] || [ ! "${barstring}" ] ; then
#!/bin/bash
current_usage=$( df -h | grep 'gfsvg-gfslv' | awk {'print '} )
echo $current_usage
critical_usage=6%
warning_usage=3%
if [[ ${current_usage%?} -lt ${warning_usage%?} ]]; then
echo OK current usage is $current_usage
elif [[ ${current_usage%?} -ge ${warning_usage%?} ]] && [[ ${current_usage%?} -lt ${critical_usage%?} ]]; then
echo Warning $current_usage
else
echo Critical $current_usage
fi