La page de manuel GNU bash pour [[..]] explique que l'opérateur exécute une expression conditionnelle et
Renvoie un statut de
0ou1en fonction de l'évaluation de l'expression conditionnelleexpression. Les expressions sont composées des primaires décrites ci-dessous dans Expressions conditionnelles Bash.
Mais l'opérateur arithmétique n'est pas une partie des expressions conditionnelles prises en charge (primaires ) à l'intérieur de [[..]] ce qui signifie que l'expression est forcée de s'exécuter comme une comparaison de chaînes, c'est-à-dire
(( $n < 3))
n'est pas exécuté dans un contexte arithmétique mais tout aussi simple comparaison lexicographique (chaîne) que
[[ 100 < 3 ]]
qui sera toujours vrai, car les valeurs ASCII pour 1 , 0 , 0 apparaître avant 3
Mais à l'intérieur du [[..]] les opérations arithmétiques sont prises en charge si vous utilisez -lt , -gt
arg1 OP arg2OP est l'un des
-eq,-ne,-lt,-le,-gt, ou-ge. Ces opérateurs binaires arithmétiques renvoient vrai siarg1est égal à, différent de, inférieur à, inférieur ou égal à, supérieur à, ou supérieur ou égal àarg2, respectivement.
Alors aviez-vous écrit votre expression comme
a=start; n=100; [[ " stop start status " =~ " $a " && $n -lt 3 ]] && echo ok || echo bad
bad
cela aurait fonctionné comme prévu.
Ou même si vous aviez forcé l'utilisation de l'expression arithmétique en préfixant $ avant ((..)) et écrit comme ci-dessous (notez que bash n'a pas de comportement documenté pour $((..)) à l'intérieur de [[..]] ). Le comportement attendu probable est que l'expression arithmétique est développée avant le [[..]] est évalué et la sortie résultante est évaluée dans un contexte de chaîne comme [[ 0 ]] ce qui signifie une chaîne non vide.
a=start; n=5; [[ " stop start status " =~ " $a " && $(( $n < 3 )) ]] && echo ok || echo bad
Le résultat aurait toujours l'air mauvais, car l'expression arithmétique à l'intérieur de [[..]] se décompose en une chaîne unaire expression de comparaison non vide comme
$(( 5 < 3 ))
0
[[ -n 0 ]]
Le résultat de l'évaluation arithmétique 0 (false) est pris comme une entité non nulle par l'opérateur de test et affirme true sur le côté droit de && . La même chose s'appliquerait également à l'autre cas, par ex. dites n=1
$(( 1 < 3 ))
1
[[ -n 1 ]]
Pour faire court, utilisez les bons opérandes pour l'opération arithmétique à l'intérieur de [[..]] .
(( est un "mot-clé" qui introduit l'instruction arithmétique. À l'intérieur de [[ , cependant, vous ne pouvez pas utiliser d'autres instructions. Vous pouvez utilisez des parenthèses pour regrouper les expressions, donc c'est ce que (( ... )) est :un "double groupe" redondant. Les éléments suivants sont tous équivalents, en raison des précédences de < et && :
[[ " stop start status " =~ " $2 " && (($#<3)) ]][[ " stop start status " =~ " $2 " && ($#<3) ]][[ " stop start status " =~ " $2 " && $#<3 ]]
Si vous voulez une comparaison d'entiers, utilisez -lt au lieu de < , mais vous n'avez pas non plus besoin de tout mettre dans [[ ... ]] . Vous pouvez utiliser une instruction conditionnelle et une instruction arithmétique ensemble dans une liste de commandes.
{ [[ " stop start status " =~ " $2 " ]] && (($#<3)) ; } || { echo "Usage $0 file_name command"; exit 1;}
Dans ce cas, ... && ... || ... fonctionnera comme prévu, bien qu'en général ce ne soit pas le cas. Préférez un if déclaration à la place.
if [[ " stop start status " =~ " $2 " ]] && (($#<3)); then
echo "Usage $0 file_name command"
exit 1
fi