Shell 参数扩展:$# 与 ${#@}
Shell parameter expansion: $# vs. ${#@}
在 shell 脚本中,据我所知,$#
和 ${#@}
的行为相同,都给出了位置参数的数量。两者之间有什么区别吗?在什么情况下,一个比另一个更可取?
${#@}
/ ${#*}
在最POSIX-likeshell中与$#
相同,但是不是 all - 一个值得注意的例外是 dash
,它在 Ubuntu 系统上充当 sh
。
$#
是 POSIX-compliant 形式,所以它是安全(便携)选择 (来自 POSIX spec,前缀 $
隐含):
#
Expands to the decimal number of positional parameters.
可选的背景信息
POSIX shell 规范主要基于历史上的 Bourne shell,其唯一的数组-like 构造是序列位置参数(</code>、<code>
、...),其中 $#
包含 count 个位置参数,$*
扩展为space-separated 参数值列表,然后受 word-splitting 和 "$@"
- 在 double-quoted 上下文中 - 扩展到最初指定的位置参数(即使它们包含嵌入的空格)。
下面分别讨论bash
、ksh
、zsh
; dash
,其行为根本不同,在底部讨论。
bash
、ksh
和 zsh
:
POSIX-compatible shell如ksh
和bash
后来推广了这个pseudo-array以提供真正的数组 变量,其语法借鉴了 positional-parameter 语法(zsh
也支持此语法,但也有自己的更简单的语法):
${arr[*]}
和"${arr[@]}"
的功能类似于$*
和"$@"
,${#arr[@]}
和${#arr[*]}
都对应于$#
.
也许是为了向原始语法致敬,这些 shell(也包括 zsh
,但其数组语法更简单)也选择支持 ${#@}
和 ${#*}
for symmetry,你可以将 @
/ *
视为 implied[ 的 all-elements 下标=121=]数组,即位置参数的pseudo-array。
关于元素的对称性提取:
类似 ${@[2]}
来镜像 </code> 的东西 <em> 仅在 </em> <code>zsh
中起作用,而不在 bash
中起作用和 ksh
.
等效的切片语法适用于所有这些,但是:${@:2:1}
dash
:
dash
,Ubuntu 系统上的默认 shell (/bin/sh
),dash
,主要限于 POSIX-only 功能,并且根本不支持数组。
因此,它将 ${#@}
/ ${#*}
区别对待 :它将 @
和 *
解释为 scalar string list 的(扩展)参数和 returns 该字符串的长度。
换句话说:在 dash
中,echo "${#@}
/ echo "${#*}
等同于:list="$@"; echo "${#list}"
.
在完全不支持数组的情况下,dash
既不支持 ${@[2]}
也不支持 ${@:2:1}
。
在 shell 脚本中,据我所知,$#
和 ${#@}
的行为相同,都给出了位置参数的数量。两者之间有什么区别吗?在什么情况下,一个比另一个更可取?
${#@}
/ ${#*}
在最POSIX-likeshell中与$#
相同,但是不是 all - 一个值得注意的例外是 dash
,它在 Ubuntu 系统上充当 sh
。
$#
是 POSIX-compliant 形式,所以它是安全(便携)选择 (来自 POSIX spec,前缀 $
隐含):
#
Expands to the decimal number of positional parameters.
可选的背景信息
POSIX shell 规范主要基于历史上的 Bourne shell,其唯一的数组-like 构造是序列位置参数(</code>、<code>
、...),其中 $#
包含 count 个位置参数,$*
扩展为space-separated 参数值列表,然后受 word-splitting 和 "$@"
- 在 double-quoted 上下文中 - 扩展到最初指定的位置参数(即使它们包含嵌入的空格)。
下面分别讨论bash
、ksh
、zsh
; dash
,其行为根本不同,在底部讨论。
bash
、ksh
和 zsh
:
POSIX-compatible shell如ksh
和bash
后来推广了这个pseudo-array以提供真正的数组 变量,其语法借鉴了 positional-parameter 语法(zsh
也支持此语法,但也有自己的更简单的语法):
${arr[*]}
和"${arr[@]}"
的功能类似于$*
和"$@"
,${#arr[@]}
和${#arr[*]}
都对应于$#
.
也许是为了向原始语法致敬,这些 shell(也包括 zsh
,但其数组语法更简单)也选择支持 ${#@}
和 ${#*}
for symmetry,你可以将 @
/ *
视为 implied[ 的 all-elements 下标=121=]数组,即位置参数的pseudo-array。
关于元素的对称性提取:
类似
${@[2]}
来镜像</code> 的东西 <em> 仅在 </em> <code>zsh
中起作用,而不在bash
中起作用和ksh
.等效的切片语法适用于所有这些,但是:
${@:2:1}
dash
:
dash
,Ubuntu 系统上的默认 shell (/bin/sh
),dash
,主要限于 POSIX-only 功能,并且根本不支持数组。
因此,它将 ${#@}
/ ${#*}
区别对待 :它将 @
和 *
解释为 scalar string list 的(扩展)参数和 returns 该字符串的长度。
换句话说:在 dash
中,echo "${#@}
/ echo "${#*}
等同于:list="$@"; echo "${#list}"
.
在完全不支持数组的情况下,dash
既不支持 ${@[2]}
也不支持 ${@:2:1}
。