16 votes

Pourquoi les opérateurs de test bash -n et -z ne sont pas inversés pour $@

function wtf() {
  echo "\$*='$*'"
  echo "\$@='$@'"
  echo "\$@='"$@"'"
  echo "\$@='""$@""'"
  if [ -n "$*" ]; then echo " [ -n \$* ]"; else echo "![ -n \$* ]"; fi
  if [ -z "$*" ]; then echo " [ -z \$* ]"; else echo "![ -z \$* ]"; fi
  if [ -n "$@" ]; then echo " [ -n \$@ ]"; else echo "![ -n \$@ ]"; fi
  if [ -z "$@" ]; then echo " [ -z \$@ ]"; else echo "![ -z \$@ ]"; fi
}

wtf

produit

$*=''
$@=''
$@=''
$@=''
![ -n $* ]
 [ -z $* ]
 [ -n $@ ]
 [ -z $@ ]

bien qu'il me semble que [-n $@] devrait être faux car 7.3 Autres opérateurs de comparaison indique que [ -n "$X" ] devrait être l'inverse de [ -z "$X" ] pour tous $X .

-z

la chaîne est nulle, c'est-à-dire qu'elle n'a pas de longueur.

String=''   # Zero-length ("null") string variable.

if [ -z "$String" ]
then
  echo "\$String is null."
else
  echo "\$String is NOT null."
fi     # $String is null.

-n

n'est pas nulle.

El -n exige que la chaîne soit citée entre les crochets du test. L'utilisation d'une chaîne non citée avec ! -z ou même la chaîne non citée seule entre des crochets de test (voir l'exemple 7-6) fonctionne normalement, mais il s'agit d'une pratique dangereuse. Toujours citer une chaîne testée. [1]

Je sais $@ est spéciale mais je ne savais pas qu'elle était assez spéciale pour violer la négation booléenne. Que se passe-t-il ici ?


$ bash -version | head -1
GNU bash, version 4.2.42(2)-release (i386-apple-darwin12.2.0)

Les codes numériques de sortie réels sont tous 1 o 0 selon

$ [ -n "$@" ]; echo "$?"
0

18voto

chepner Points 54078

Quand $@ est vide, "$@" ne se développe pas en une chaîne vide ; elle est supprimée complètement. Votre test n'est donc pas

[ -n "" ]

mais plutôt

[ -n ]

Maintenant -n n'est pas un opérateur, mais juste une chaîne non vide, qui est toujours testée comme vraie.

3voto

Aaron Digulla Points 143830

"$@" ne fait pas ce que vous attendez. Ce n'est pas une forme différente de "$*" il s'étend à la liste citée des arguments passés au script actuel.

S'il n'y a pas d'arguments, il s'étend à rien. S'il y a deux arguments a y b c puis il s'étend à "a" "b c" (c'est-à-dire qu'il préserve les espaces dans les arguments) alors que "$*" s'étend à "a b c" y $* s'étendrait à a b c (trois mots).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X