$#
est le nombre d'arguments, mais rappelez-vous qu'il sera différent dans une fonction.
$#
est le nombre de paramètres positionnels transmis au script, au shell ou à la fonction shell . En effet, lors de l'exécution d'une fonction shell, les paramètres positionnels sont temporairement remplacés par les arguments de la fonction . Cela permet aux fonctions d'accepter et d'utiliser leurs propres paramètres de position.
Ce script s'imprime toujours 3
, quel que soit le nombre d'arguments transmis au script lui-même, car "$#"
dans la fonction f
s'étend au nombre d'arguments transmis à la fonction:
#!/bin/sh
f() {
echo "$#"
}
f a b c
Ceci est important car cela signifie que du code comme celui-ci ne fonctionne pas comme vous pouvez vous y attendre, si vous n'êtes pas familier avec le fonctionnement des paramètres de position dans les fonctions shell:
#!/bin/sh
check_args() { # doesn't work!
if [ "$#" -ne 2 ]; then
printf '%s: error: need 2 arguments, got %d\n' "$0" "$#" >&2
exit 1
fi
}
# Maybe check some other things...
check_args
# Do other stuff...
Dans check_args
, $#
s'étend au nombre d'arguments passés à la fonction elle-même, qui dans ce script est toujours 0.
Si vous voulez une telle fonctionnalité dans une fonction shell, vous devez écrire quelque chose comme ceci à la place:
#!/bin/sh
check_args() { # works -- the caller must pass the number of arguments received
if [ "$1" -ne 2 ]; then
printf '%s: error: need 2 arguments, got %d\n' "$0" "$1" >&2
exit 1
fi
}
# Maybe check some other things...
check_args "$#"
Cela fonctionne car $#
est développé en dehors de la fonction et transmis à la fonction comme l'un de ses paramètres de position. À l'intérieur de la fonction, se $1
développe au premier paramètre positionnel qui a été passé à la fonction shell, plutôt qu'au script dont elle fait partie.
Ainsi, comme $#
les paramètres spéciaux $1
, $2
etc., ainsi que $@
et $*
, se rapportent également aux arguments passés à une fonction, quand ils sont étendus dans la fonction. Cependant, $0
ne pas changer le nom de la fonction, ce qui est la raison pour laquelle j'étais encore capable de l' utiliser pour produire un message d'erreur de qualité.
$ ./check-args-demo a b c
./check-args-demo: error: need 2 arguments, got 3
De même, si vous définissez une fonction à l'intérieur d'une autre, vous travaillez avec les paramètres de position passés à la fonction la plus interne dans laquelle l'expansion est effectuée:
#!/bin/sh
outer() {
inner() {
printf 'inner() got %d arguments\n' "$#"
}
printf 'outer() got %d arguments\n' "$#"
inner x y z
}
printf 'script got %d arguments\n' "$#"
outer p q
J'ai appelé ce script nested
et (après avoir exécuté chmod +x nested
) je l'ai exécuté:
$ ./nested a
script got 1 arguments
outer() got 2 arguments
inner() got 3 arguments
Oui je sais. "1 arguments" est un bug de pluralisation.
Les paramètres de position peuvent également être modifiés.
Si vous écrivez un script, les paramètres positionnels en dehors d'une fonction seront les arguments de ligne de commande passés au script, sauf si vous les avez modifiés .
Une façon courante de les changer est avec la fonction shift
intégrée, qui décale chaque paramètre de position vers la gauche d'un, en supprimant le premier et en diminuant $#
de 1:
#!/bin/sh
while [ "$#" -ne 0 ]; do
printf '%d argument(s) remaining.\nGot "%s".\n\n' "$#" "$1"
shift
done
$ ./do-shift foo bar baz # I named the script do-shift.
3 argument(s) remaining.
Got "foo".
2 argument(s) remaining.
Got "bar".
1 argument(s) remaining.
Got "baz".
Ils peuvent également être modifiés avec la fonction set
intégrée:
#!/bin/sh
printf '%d args: %s\n' "$#" "$*"
set foo bar baz
printf '%d args: %s\n' "$#" "$*"
$ ./set-args a b c d e # I named the script set-args.
5 args: a b c d e
3 args: foo bar baz
$#
? Que veux-tu accomplir? Où avez-vous obtenu cette commande. Ce n'est pas du tout pertinent.