在一个 shell 脚本中,据我所知,$#
并且${#@}
行为相同,都给出了位置参数的数量。两者之间有什么区别,在什么情况下一个比另一个更可取?
1 回答
${#@}
/${#*}
与大多数类似 POSIX 的 shell 相同,但不是$#
全部-一个值得注意的例外是,它在 Ubuntu 系统上起作用。dash
sh
$#
是符合 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 。zsh
bash
ksh
但是,等效的切片语法适用于所有这些:
${@:2:1}
dash
:
dash
, Ubuntu 系统上的默认 shell ( /bin/sh
) dash
, 主要限于 POSIX-only 功能, 根本不支持数组。
因此,它对待${#@}
/${#*}
不同:它将@
和解释*
为(扩展的)参数的标量字符串列表并返回该字符串的长度。
换句话说: in dash
, echo "${#@}
/echo "${#*}
等价于:list="$@"; echo "${#list}"
。
在完全不支持数组的情况下,dash
合适地既不支持${@[2]}
也不支持${@:2:1}
.