$#
是参数的数量,但请记住函数中的参数将有所不同。
$#
是传递给脚本,shell 或shell函数的位置参数的数量。这是因为在运行Shell函数时,位置参数会临时替换为该函数的参数。这使函数可以接受并使用自己的位置参数。
3
不管传递给脚本本身多少参数,该脚本始终都会打印,因为"$#"
在函数中f
扩展为传递给函数的参数数量:
#!/bin/sh
f() {
echo "$#"
}
f a b c
这很重要,因为如果您不熟悉位置参数在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...
在中check_args
,$#
扩展为传递给函数本身的参数数量,在该脚本中始终为0。
如果要在shell函数中使用此类功能,则必须编写如下代码:
#!/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 "$#"
之所以起作用,$#
是因为在函数外部进行了扩展,并作为其位置参数之一传递给了函数。在函数内部,$1
扩展到传递给shell函数的第一个位置参数,而不是传递给它所属的脚本。
因此,$#
当特殊参数$1
,$2
等等以及和$@
和$*
一起在函数中扩展时,它们也与传递给函数的参数有关。但是,$0
并没有更改函数的名称,这就是为什么我仍然能够使用它来生成质量错误消息的原因。
$ ./check-args-demo a b c
./check-args-demo: error: need 2 arguments, got 3
同样,如果您在另一个函数中定义一个函数,则需要使用传递给执行扩展的最内部函数的位置参数:
#!/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
我调用了该脚本,nested
并(在运行之后chmod +x nested
)运行了它:
$ ./nested a
script got 1 arguments
outer() got 2 arguments
inner() got 3 arguments
是的我知道。“ 1个参数”是一个复数错误。
位置参数也可以更改。
如果您正在编写脚本,则函数外部的位置参数将是传递给脚本的命令行参数,除非您对其进行了更改。
更改它们的一种常见方法是使用shift
内置函数,该函数将每个位置参数向左移动一个,将第一个位置减小$#
,然后减小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".
也可以使用set
内置函数来更改它们:
#!/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
$#
?您想实现什么?您从何处获得此命令。它根本不相关。