在shell脚本中,据我所知,$#
和${#@}
的行为相同,两者都给出了位置参数的数量。这两者之间是否存在差异?在哪种情况下,哪一种优于另一种?
答案 0 :(得分:5)
${#@}
/ ${#*}
与大多数类似POSIX的shell中的$#
相同,但不是 all - 值得注意的异常是dash
,在Ubuntu系统上充当sh
。
$#
是符合POSIX标准的表单,因此它是安全(可移植)选项(来自POSIX spec,隐含前缀$
):< / p>
#
扩展为位置参数的十进制数。
POSIX shell规范主要基于历史Bourne shell,其唯一的array- like 构造是位置参数序列($1
,$2
,.. 。),$#
包含位置参数的 count ,$*
扩展到以空格分隔的参数值列表,然后进行分词,{ {1}} - 在双引号上下文中 - 扩展到最初指定的位置参数(即使它们包含嵌入的空格)。
以下讨论"$@"
,bash
和ksh
; zsh
,根本不同的行为,在底部讨论。
dash
,bash
和ksh
:
POSIX兼容的shell(例如zsh
和ksh
)后来推广了这个伪数组以提供真正的数组变量,其语法借用了位置参数语法( bash
也支持这种语法,但也有自己的,更简单的语法):
zsh
和${arr[*]}
的功能类似于"${arr[@]}"
和$*
,"$@"
和${#arr[@]}
都对应${#arr[*]}
。
也许是对原始语法的点头,这些shell(也包括$#
,其数组语法更简单)也选择支持zsh
和${#@}
对称,您可以将${#*}
/ @
视为隐含数组的全元素下标,即位置参数的伪数组
关于元素提取的对称性:
*
镜像${@[2]}
之类的内容仅适用于$2
中 ,而不是zsh
和bash
。
等效切片语法适用于所有这些语法:ksh
<强> ${@:2:1}
强>:
dash
,Ubuntu系统上的默认shell(dash
)/bin/sh
,主要仅限于POSIX功能,并且根本不支持数组。
因此,它以不同的方式对待dash
/ ${#@}
:它将${#*}
和@
解释为标量 string list (扩展)参数并返回该字符串的长度
换句话说:在*
中,dash
/ echo "${#@}
相当于:echo "${#*}
。
如果没有完全支持数组,list="$@"; echo "${#list}"
恰好既不支持dash
也不支持${@[2]}
。