Je pense que la recommandation que vous avez vue était pour POSIX sh et / ou la testcommande qui se double de la [commande, plutôt que la [[construction qui est apparue dans ksh (merci Stéphane Chazelas pour l'astuce) et est également utilisée par exemple dans bash, zsh et quelques autres coquilles.
Dans la plupart des langages, comme C, lorsqu'une clause est déjà connue pour être vraie ou fausse, il n'est pas nécessaire d'évaluer les parties restantes en fonction de l'opération: si vrai pas après une logique ou la suivant, si faux pas après une logique et , etc. Ceci permet bien sûr par exemple de s'arrêter lorsqu'un pointeur est NULL et de ne pas essayer de le déréférencer dans la clause suivante.
Mais la construction de sh[ expr1 -o expr2 ] (y compris l'implémentation de bash) ne fait pas cela: elle évalue toujours les deux côtés, quand on voudrait que seulement expr1 soit évalué. Cela pourrait avoir été fait pour la compatibilité avec l' testimplémentation de la commande. En revanche, sh's ||et &&do suivent le principe habituel: non évalué s'il ne modifie pas le résultat.
La différence à noter serait donc:
: > /tmp/effect #clear effect
if [ 1 -eq 1 -o $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
ce qui donne:
true
or-was-evaluated
Ci-dessus, chacun [aurait pu être remplacé par /usr/bin/[un alias de la testcommande, utilisé avant d' [être intégré aux obus.
Alors que les deux constructions suivantes:
: > /tmp/effect #clear effect
if [ 1 -eq 1 ] || [ $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]; then
echo true;
fi
cat /tmp/effect
ou
: > /tmp/effect #clear effect
if [[ 1 -eq 1 || $(echo 1; echo or-was-evaluated > /tmp/effect) -eq 1 ]]; then
echo true;
fi
cat /tmp/effect
Ne cède que trueet laisse effectvide: ||se comporte correctement et [[corrige également ce problème.
MISE À JOUR:
Comme l'a commenté @ StéphaneChazelas, j'ai raté plusieurs différences liées à la question initiale. Je vais mettre ici le plus important (du moins pour moi): la priorité des opérateurs.
Bien que le shell ne considère pas la priorité:
if true || true && false; then
echo true
else
echo false
fi
donne (car il n'y a pas de priorité et donc true || trueest d' abord évalué, puis && false):
false
à [[ ]]l' intérieur de l' &&opérateur a priorité sur ||:
if [[ 1 -eq 1 || 1 -eq 1 && 1 -eq 0 ]]; then
echo true
else
echo false
fi
rendements (car 1 -eq 1 && 1 -eq 0est groupé et est donc le 2ème membre de ||):
true
au moins pour ksh , bash , zsh .
A donc [[ ]]amélioré le comportement sur les deux [ ]et les opérateurs logiques shell direct.
[outest( pas[[), recherchez lesOBbalises (liées à la définition "obsolète") dans la spécification POSIX pourtest. Danstest, il y a des cas pathologiques où il peut être impossible de dire si(ou)est censé avoir une signification syntaxique pour la commande de test ou une chaîne à tester, donc les personnes qui ignorent les marqueurs d'obsolescence et utilisent cette syntaxe peuvent en fait avoir besoin du contraire -"x$foo"pratique obsolète ; avec[[, ce n'est pas un problème.