Shell参数扩展:$#vs. $ {#@}

时间:2017-01-26 03:23:02

标签: bash shell parameter-expansion

在shell脚本中,据我所知,$#${#@}的行为相同,两者都给出了位置参数的数量。这两者之间是否存在差异?在哪种情况下,哪一种优于另一种?

1 个答案:

答案 0 :(得分:5)

${#@} / ${#*}大多数类似POSIX的shell中的$#相同,但不是 all - 值得注意的异常是dash,在Ubuntu系统上充当sh

$#是符合POSIX标准的表单,因此它是安全(可移植)选项(来自POSIX spec,隐含前缀$):< / p>

  

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

可选背景信息

POSIX shell规范主要基于历史Bourne shell,其唯一的array- like 构造是位置参数序列($1$2,.. 。),$#包含位置参数的 count $*扩展到以空格分隔的参数值列表,然后进行分词,{ {1}} - 在双引号上下文中 - 扩展到最初指定的位置参数(即使它们包含嵌入的空格)。

以下讨论"$@"bashksh; zsh,根本不同的行为,在底部讨论。

dashbashksh

POSIX兼容的shell(例如zshksh)后来推广了这个伪数组以提供真正的数组变量,其语法借用了位置参数语法( bash也支持这种语法,但也有自己的,更简单的语法):

zsh${arr[*]}的功能类似于"${arr[@]}"$*"$@"${#arr[@]}都对应${#arr[*]}

也许是对原始语法的点头,这些shell(也包括$#,其数组语法更简单)也选择支持zsh${#@} 对称,您可以将${#*} / @视为隐含数组的全元素下标,即位置参数的伪数组

关于元素提取的对称性

  • *镜像${@[2]}之类的内容仅适用于$2 ,而不是zshbash

  • 等效切片语法适用于所有这些语法:ksh

<强> ${@:2:1}

dash,Ubuntu系统上的默认shell(dash/bin/sh,主要仅限于POSIX功能,并且根本不支持数组。

因此,它以不同的方式对待dash / ${#@} :它将${#*}@解释为标量 string list (扩展)参数并返回该字符串的长度 换句话说:在*中,dash / echo "${#@}相当于:echo "${#*}

如果没有完全支持数组,list="$@"; echo "${#list}"恰好既不支持dash也不支持${@[2]}