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 celle qui montre si ....
Quel est le problème avec cette condition? Je suppose que quelque chose ne va pas avec le ()
.
Technique classique (métacaractères d'échappement):
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 car la priorité de -a
et -o
le rend correct même sans elles.
Notez que les opérateurs -a
et -o
font partie de la spécification POSIX pour test
, également appelé [
, principalement pour des raisons de compatibilité ascendante (puisqu'ils faisaient partie de test
dans 7th Edition UNIX, par exemple), mais ils sont explicitement marqués comme 'obsolescente' de POSIX. Bash (voir expressions conditionnelles ) semble préempter les significations classiques et POSIX pour -a
et -o
avec ses propres opérateurs alternatifs qui prennent des arguments.
Avec un peu de prudence, vous pouvez utiliser l'opérateur plus moderne [[
, mais sachez que les versions de Bash et de Korn Shell (par exemple) ne doivent pas nécessairement ê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 exécuté avec Bash 3.2.57 sous 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 avec [
car il ne s'agit pas d'une commande séparée de la même manière que [
.
N'est-ce pas une question classique?
Je l'aurais pensé. Cependant, il existe une autre alternative, à 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 les instructions de '' shell portable '' pour l'outil autoconf
ou les packages associés, cette notation - utilisant '||
' et '&&
' - correspond à leurs recommandations. Je suppose que vous pourriez même aller aussi loin que:
if [ "$g" -eq 1 ] && [ "$c" = "123" ]
then echo abc
Elif [ "$g" -eq 2 ] && [ "$c" = "456" ]
then echo abc
else echo efg
fi
Là où les actions sont aussi triviales que l'é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 pénible et l'une des versions antérieures est préférable: vous devez également intégrer les actions à une fonction appelée dans les différents blocs then
.
Dans Bash:
if [[ ( $g == 1 && $c == 123 ) || ( $g == 2 && $c == 456 ) ]]
En utilisant /bin/bash
, ce qui suit fonctionnera:
if [ "$option" = "Y" ] || [ "$option" = "y" ]; then
echo "Entered $option"
fi
Faites attention si vous avez des espaces dans vos variables de chaîne et que vous vérifiez leur existence. Assurez-vous de les citer correctement.
if [ ! "${somepath}" ] || [ ! "${otherstring}" ] || [ ! "${barstring}" ] ; then
$ 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
#!/bin/bash
current_usage=$( df -h | grep 'gfsvg-gfslv' | awk {'print $5'} )
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