为什么要使用 zsh 数组参数?

Mik*_*e B 5 zsh

list=(1 2 3)
for i in $list; do echo $i; done;
for i in $list[@]; do echo $i; done;
for i in $list[*]; do echo $i; done;
for i in ${list}; do echo $i; done;
for i in ${list[@]}; do echo $i; done;
for i in ${list[*]}; do echo $i; done;
for i in "${list[@]}"; do echo $i; done;
Run Code Online (Sandbox Code Playgroud)

所有这些都打印相同的内容:

1 
2
3
Run Code Online (Sandbox Code Playgroud)

这些

for i in "$list"; do echo $i; done;
for i in "${list}"; do echo $i; done;
for i in "$list[*]"; do echo $i; done;
for i in "${list[*]}"; do echo $i; done;
Run Code Online (Sandbox Code Playgroud)

全部打印

1 2 3
Run Code Online (Sandbox Code Playgroud)

什么时候应该使用括号、什么时候不使用括号、什么时候应该使用@括号*?例如,我知道和 之间的区别 ,但我无法找到关于, , , , , 和之间区别的直接答案。当我可以这样做时为什么要使用数组参数?"${list[@]}""${list[*]}"$list${list}$list[@]${list[@]}$list[*]${list[*]}$list

"$list"同样,当我希望数组中的所有元素都在一个字符串中时,为什么不呢?在这种情况下,我疯狂地有4 个不同的选择:"$list""${list}""$list[*]""${list[*]}"

hch*_*baw 6

一般来说,使用哪个取决于我们。但深入研究为什么 zsh 允许编写这样的代码可能是值得的。

来自 zsh FAQ 文档:

1.2:这是什么?

Zsh 是一个 UNIX 命令解释器 (shell),它是最类似于 Korn shell (ksh) 的标准 shell;

--- 第 1 章:介绍 zsh 以及如何安装它,Z-Shell 常见问题

和,

第 2 章:zsh 与...有何不同?

正如已经提到的,zsh 与 ksh 最相似,而许多添加都是为了取悦 csh 用户。

...

2.1:与sh和ksh的区别

ksh(以及 sh)的大多数功能都是在 zsh 中实现的;由于实现略有不同,可能会出现问题。

--- 第 2 章:zsh 与...有何不同?,Z-Shell 常见问题

我告诉自己,当我编写自己的 zsh 脚本时,应该注意 zsh 有很多类似 ksh 的功能和模拟选项。您也可以尝试一下setopt ksh_arrays,看看发生了什么。

数组(默认情况下)比 ksh 更像 csh:下标从 1 开始,而不是 0;array[0]指的是array[1]$array指整个数组,而不是$array[0]; 大括号是不必要的:$a[1]==${a[1]}等。设置KSH_ARRAYS兼容性选项。

--- 2.1:与sh和ksh的区别,Z-Shell常见问题

它可以通过显示与 ksh 的一些比较来给出一些提示/答案。

带括号与不带括号

Q22. 为什么数组引用需要大括号,例如${x[1]}

A22。这样做固然很好$x[1],但 POSIX shell 会展开$x,然后搜索通过连接产生的文件模式[1]。ksh 与 POSIX 兼容。

--- III SHELL 编程问题 Q22、KSH-93 - 常见问题

ksh 像这样处理数组参数:

list=(a b c)
echo $list[1]
;# => "a[1]"
;# concatination of the first $list element and "[1]" string
;# rather than below!
echo ${list[1]} ;# => "b"
Run Code Online (Sandbox Code Playgroud)

因此,它可以在第一个示例中使用$list${list}$list[@]${list[@]}、 、$list[*]和中的任何一个;${list[*]}它可以被认为是 zsh 的一个特性。

$x[1]您可以通过阅读上面的 ksh 文档的to$list[@]或 来从另一个角度查看代码$list[*]

注意:在 zsh 中,如果$list包含空值,则"${list[@]}"根据“ 24. 空参数删除”有所不同。

24. 空参数删除

如果替换未出现在双引号中,则任何生成的零长度参数(无论是来自标量还是数组元素)都会从插入到命令行的参数列表中删除。

--- 24. 空参数删除、规则、扩展、zshparam(1)

@*

Q1. 例如, 和 之间*有什么区别?@

A1。当在 之外使用时"",它们是等效的。但是,在双引号内,"$@"为每个位置参数生成一个参数,并"$*"生成单个参数。请注意,"$@"保留参数列表,而$*除非禁用分词和路径名扩展,否则可能不会。

--- III SHELL 编程问题 Q1、KSH-93 - 常见问题

如您所知,前半部分与 zsh 相同。这是您建议的 zsh 文档的相同参考:

形式的下标[*]or[@]计算数组的所有元素;两者之间没有区别,除非它们出现在双引号内。

"$foo[*]"计算结果为"$foo[1] $foo[2] ...",而"$foo[@]"计算结果为"$foo[1]" "$foo[2]" ...

...

当数组参数被引用为$name(无下标)时,其计算结果为$name[*],

--- 数组下标,zshparam(1)

"$list"与其他人相比

正如您所看到的,zsh 为我们提供了 4 种不同的选项作为其功能。但我认为 ksh 用户可以这样说:

"$list""${list}"并且"$list[*]"可能意味着它将仅对第一个元素(以及后者的$list连接结果)而不是列表/数组引用执行一些操作。"[*]"


这是一个示例代码:

list=(1 2 '' 3) # XXX: added an empty entry to check the difference

test-list-dq () {
  echo "$1"
  local i=
  echo '$list:';        for i in $list; do echo $i; done;
  echo '$list[@]:';     for i in $list[@]; do echo $i; done;
  echo '$list[*]:';     for i in $list[*]; do echo $i; done;
  echo '${list}:';      for i in ${list}; do echo $i; done;
  echo '${list[@]}:';   for i in ${list[@]}; do echo $i; done;
  echo '${list[*]}:';   for i in ${list[*]}; do echo $i; done;
  echo '"${list[@]}":'; for i in "${list[@]}"; do echo $i; done;
}

test-list-nq () {
  echo "$1"
  local i=
  for i in "$list"; do echo $i; done
  for i in "${list}"; do echo $i; done
  for i in "$list[*]"; do echo $i; done
  for i in "${list[*]}"; do echo $i; done
}

echo "*double quotes"
test-list-dq "*default"
()  {
  setopt localoptions ksharrays no_nomatch
  test-list-dq "*ksharrays on"
}

echo "*no quotes"
test-list-nq "*default"
()  {
  setopt localoptions ksharrays no_nomatch
  test-list-nq "*ksharrays on"
}
Run Code Online (Sandbox Code Playgroud)

输出如下:

*double quotes
*default
$list:
1
2
3
$list[@]:
1
2
3
$list[*]:
1
2
3
${list}:
1
2
3
${list[@]}:
1
2
3
${list[*]}:
1
2
3
"${list[@]}":
1
2

3
*ksharrays on
$list:
1
$list[@]:
1[@]
$list[*]:
1[*]
${list}:
1
${list[@]}:
1
2
3
${list[*]}:
1
2
3
"${list[@]}":
1
2

3
*no quotes
*default
1 2  3
1 2  3
1 2  3
1 2  3
*ksharrays on
1
1
1[*]
1 2  3
Run Code Online (Sandbox Code Playgroud)