$#
est le nombre d'arguments, mais n'oubliez pas qu'il sera différent dans une fonction.
$#
est le nombre de paramètres positionnels passés au script, script, ou la fonction Shell. . En effet, pendant qu'une fonction Shell est en cours d'exécution, la fonction 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 positionnels.
Ce script imprime toujours 3
quel que soit le nombre d'arguments passés au script lui-même, parce que "$#"
dans la fonction f
s'étend au nombre d'arguments passés à la fonction :
#!/bin/sh
f() {
echo "$#"
}
f a b c
C'est important car cela signifie que le code comme celui-ci ne fonctionne pas comme vous pourriez vous y attendre, si vous n'êtes pas familier avec la façon dont les paramètres positionnels fonctionnent 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...
Sur 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 devrez é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 parce que $#
est élargi à l'extérieur de la fonction et transmis à la fonction comme l'un des éléments suivants son paramètres de position. A l'intérieur de la fonction, $1
s'étend au premier paramètre positionnel qui a été passé à la fonction Shell, plutôt qu'au Shell dont elle fait partie.
Ainsi, comme $#
les paramètres spéciaux $1
, $2
etc., ainsi que $@
y $*
se rapportent également aux arguments passés à une fonction, lorsqu'ils sont développés dans la fonction. Cependant, $0
fait ノット au nom de la fonction, ce qui explique que j'ai pu 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 positionnels transmis à 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 fait :
$ ./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 la ligne de commande passés au script. à moins que vous ne les ayez changés .
Une façon courante de les modifier est d'utiliser la fonction shift
qui décale chaque paramètre positionnel vers la gauche d'une unité, en supprimant le premier et en diminuant le second. $#
par 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
builtin :
#!/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