$#
ist die Anzahl der Argumente, aber denken Sie daran, dass es in einer Funktion anders sein wird.
$#
ist die Anzahl der Positionsparameter, die an das Skript, die Shell oder die Shell-Funktion übergeben werden . Dies liegt daran, dass während der Ausführung einer Shell-Funktion die Positionsparameter vorübergehend durch die Argumente der Funktion ersetzt werden . Auf diese Weise können Funktionen ihre eigenen Positionsparameter akzeptieren und verwenden.
Dieses Skript wird immer gedruckt 3
, unabhängig davon, wie viele Argumente an das Skript selbst übergeben wurden, da "$#"
in der Funktion f
die Anzahl der an die Funktion übergebenen Argumente erweitert wird:
#!/bin/sh
f() {
echo "$#"
}
f a b c
Dies ist wichtig, da Code wie dieser möglicherweise nicht wie erwartet funktioniert, wenn Sie nicht mit der Funktionsweise von Positionsparametern in Shell-Funktionen vertraut sind:
#!/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...
In check_args
, wird $#
auf die Anzahl der Argumente erweitert, die an die Funktion selbst übergeben werden. In diesem Skript ist dies immer 0.
Wenn Sie eine solche Funktionalität in einer Shell-Funktion wünschen, müssen Sie stattdessen Folgendes schreiben:
#!/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 "$#"
Dies funktioniert, weil $#
es außerhalb der Funktion erweitert und als einer seiner Positionsparameter an die Funktion übergeben wird. Wird in der Funktion $1
zum ersten Positionsparameter erweitert, der an die Shell-Funktion und nicht an das Skript übergeben wurde, zu dem sie gehört.
So wie $#
die speziellen Parameter $1
, $2
usw., sowie $@
und $*
auch an die an eine Funktion übergebenen Argumente beziehen sich , wenn sie in der Funktion erweitert werden. Es $0
ändert sich jedoch nichts an dem Namen der Funktion, weshalb ich sie immer noch verwenden konnte, um eine Qualitätsfehlermeldung zu erzeugen.
$ ./check-args-demo a b c
./check-args-demo: error: need 2 arguments, got 3
Wenn Sie eine Funktion in einer anderen definieren, arbeiten Sie auf ähnliche Weise mit den Positionsparametern, die an die innerste Funktion übergeben werden, in der die Erweiterung ausgeführt wird:
#!/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
Ich habe dieses Skript aufgerufen nested
und (nach dem Ausführen chmod +x nested
) ausgeführt:
$ ./nested a
script got 1 arguments
outer() got 2 arguments
inner() got 3 arguments
Ja, ich weiß. "1 Argumente" ist ein Pluralisierungsfehler.
Die Positionsparameter können auch geändert werden.
Wenn Sie ein Skript schreiben, sind die Positionsparameter außerhalb einer Funktion die Befehlszeilenargumente, die an das Skript übergeben werden, sofern Sie sie nicht geändert haben .
Eine gebräuchliche Möglichkeit, sie zu ändern, ist die shift
Verwendung des eingebauten Parameters, der jeden Positionsparameter um eins nach links verschiebt, den ersten um eins senkt und um eins verringert $#
:
#!/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".
Sie können auch mit dem set
eingebauten geändert werden :
#!/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
$#
? Was willst du erreichen Woher hast du diesen Befehl? Es ist überhaupt nicht relevant.