1

在一个 shell 脚本中,据我所知,$#并且${#@}行为相同,都给出了位置参数的数量。两者之间有什么区别,在什么情况下一个比另一个更可取?

4

1 回答 1

5

${#@}/${#*}大多数类似 POSIX 的 shell 相同,但不是$#全部-一个值得注意的例外是,它在 Ubuntu 系统上起作用。dashsh

$#是符合 POSIX 的形式,因此它是安全(便携)的选择(来自POSIX 规范$,隐含前缀):

#扩展为位置参数的十进制数。


可选的背景信息

POSIX shell 规范主要基于历史悠久的 Bourne shell,其唯一类似数组的构造是位置参数序列 ( $1, $2, ...),$#包含位置参数的计数$*扩展为空格分隔的然后进行分词的参数值,并且"$@"- 在双引号上下文中 - 扩展到最初指定的位置参数(即使它们包含嵌入的空格)。

下面讨论bash,kshzsh; dash,它的作用根本不同,在底部进行了讨论。

bash, ksh, 和zsh:

POSIX 兼容的 shell,例如kshbash后来推广这个伪数组以提供真正的数组变量,其语法从位置参数语法中借用(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}.

于 2017-01-26T03:26:52.797 回答