在一个 shell 脚本中,据我所知,$#并且${#@}行为相同,都给出了位置参数的数量。两者之间有什么区别,在什么情况下一个比另一个更可取?
1 回答
${#@}/${#*}与大多数类似 POSIX 的 shell 相同,但不是$#全部-一个值得注意的例外是,它在 Ubuntu 系统上起作用。dashsh
$#是符合 POSIX 的形式,因此它是安全(便携)的选择(来自POSIX 规范$,隐含前缀):
#扩展为位置参数的十进制数。
可选的背景信息
POSIX shell 规范主要基于历史悠久的 Bourne shell,其唯一类似数组的构造是位置参数序列 ( $1, $2, ...),$#包含位置参数的计数,$*扩展为空格分隔的然后进行分词的参数值,并且"$@"- 在双引号上下文中 - 扩展到最初指定的位置参数(即使它们包含嵌入的空格)。
下面讨论bash,ksh和zsh; dash,它的作用根本不同,在底部进行了讨论。
bash, ksh, 和zsh:
POSIX 兼容的 shell,例如ksh和 bash后来推广这个伪数组以提供真正的数组变量,其语法从位置参数语法中借用(zsh也支持这种语法,但也有自己的更简单的语法):
${arr[*]}和"${arr[@]}"的功能类似于$*和"$@",两者${#arr[@]}和${#arr[*]}对应于$#。
也许是为了向原始语法致敬,这些 shell(也包括zsh,但其数组语法更简单)也选择支持${#@}和${#*} 对称性,您可以将@/*视为隐含数组的所有元素下标,即,位置参数的伪数组。
至于关于元素提取的对称性:
像
${@[2]}镜像这样的东西只适用$2于,而不适用于and 。zshbashksh但是,等效的切片语法适用于所有这些:
${@:2:1}
dash:
dash, Ubuntu 系统上的默认 shell ( /bin/sh) dash, 主要限于 POSIX-only 功能, 根本不支持数组。
因此,它对待${#@}/${#*} 不同:它将@和解释*为(扩展的)参数的标量字符串列表并返回该字符串的长度。
换句话说: in dash, echo "${#@}/echo "${#*}等价于:list="$@"; echo "${#list}"。
在完全不支持数组的情况下,dash合适地既不支持${@[2]}也不支持${@:2:1}.