在一个shell脚本,据我所知,$#
和${#@}
相同的行为,既给位置参数的个数.这两者之间是否存在差异?在哪种情况下,哪一种优于另一种?
${#@}
/ ${#*}
是一样的$#
在大多数 POSIX般的炮弹,但不是全部 -一个值得注意的例外是dash
,它作为sh
在Ubuntu系统.
$#
是符合POSIX的表单,因此它是安全(可移植)选项(来自POSIX规范,$
暗示前缀):
#
扩展为位置参数的十进制数.
POSIX的壳规范在很大程度上是基于历史的Bourne壳,其唯一的基于阵列等构建体是位置参数(的序列$1
,$2
,...),与$#
含有计数位置参数,$*
扩展到的一个空格分隔的列表然后进行分词的参数值,以及"$@"
- 在双引号上下文中 - 扩展到最初指定的位置参数(即使它们包含嵌入的空格).
下面讨论bash
,ksh
和zsh
; dash
在底部讨论了根本不同的行为.
bash
,ksh
以及zsh
:
POSIX兼容的外壳如ksh
和 bash
后来推广这种伪阵列提供真正的数组变量,从位置参数语法借用其语法(zsh
支持这种语法太,但有自己的,简单的语法以及):
${arr[*]}
并且"${arr[@]}"
类似地起作用以$*
及"$@"
,都${#arr[@]}
和${#arr[*]}
对应$#
.
也许是对原始语法的点头,这些shell(也包括zsh
,其数组语法更简单)也选择支持${#@}
和${#*}
对称,在这里你可以将@
/ *
视为隐含数组的全元素下标,即,位置参数的伪数组.
至于元素提取的对称性:
喜欢的东西${@[2]}
到镜子$2
的作品只在zsh
,不bash
和ksh
.
但是,等效切片语法适用于所有这些语法: ${@:2:1}
dash
:
dash
,/bin/sh
Ubuntu系统上的默认shell()dash
主要限于仅POSIX功能,并且根本不支持数组.
因此,它处理${#@}
/ ${#*}
不同:它解释@
并*
作为(扩展)参数的标量字符串列表并返回该字符串的长度.
换句话说:in dash
,echo "${#@}
/ echo "${#*}
相当于:list="$@"; echo "${#list}"
.
在完全dash
不支持阵列的情况下,既不支持${@[2]}
也不支持${@:2:1}
.