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

时间:2018-07-18 21:59:36

标签: 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;

所有这些都打印相同的东西:

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;

所有打印

1 2 3

我什么时候应该使用方括号而不是方括号,以及@*?例如,我know the difference between "${list[@]}""${list[*]}",但是我无法找到关于$list${list},{{ 1}},$list[@]${list[@]}$list[*]。为什么我只能做${list[*]}时才使用数组参数?

类似地,当我希望数组中的所有元素都在一个字符串中时,为什么我不只是$list?在那种情况下,我会有 4 个不同的选项:"$list""$list""${list}""$list[*]"

2 个答案:

答案 0 :(得分:2)

尝试

list=('a b' $'c\nd')

还要将$IFS设置为例如'|'来了解${list[*]}的工作原理。

list=('a b' $'c\nd')
IFS='|'
printf %s "${list[*]}"

答案 1 :(得分:1)

通常,使用哪个取决于我们。但是可能值得研究一下zsh为何允许编写此类代码。

来自zsh常见问题解答文件:

  

1.2:什么?

     

Zsh是UNIX命令解释器(shell),其标准外壳程序与Korn shell(ksh)最相似;

     

--- Chapter 1: Introducing zsh and how to install it, Z-Shell Frequently-Asked Questions

  

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

     

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

     

...

     

2.1:与sh和ksh的区别

     

ksh(因此还有sh)的大多数功能都在zsh中实现;可能会出现问题,因为实现方式略有不同。

     

--- Chapter 2: How does zsh differ from...?, Z-Shell Frequently-Asked Questions

我告诉自己,应该注意的是,当我编写自己的zsh脚本时,zsh具有许多类似ksh的功能和仿真选项。您也可以尝试setopt ksh_arrays来看看发生了什么。

  

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

     

--- 2.1: Differences from sh and ksh, Z-Shell Frequently-Asked Questions

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

方括号与无方括号

  

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

     

A22。进行$x[1]会很不错,但是POSIX Shell会展开$x,然后搜索通过串联[1]产生的文件模式。 ksh与POSIX兼容。

     

--- III SHELL PROGRAMMING QUESTIONS Q22, KSH-93 - Frequently Asked Questions

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"

因此,可以在第一个$list${list}$list[@]${list[@]}$list[*]${list[*]}中使用它例;它可以被视为zsh的功能。

您可以从ksh文档的$x[1]$list[@]$list[*]的上方从另一个角度查看代码。

注意:在zsh中,如果$list包含空值,则"${list[@]}"会根据“ 24. Empty argument removal”而有所不同。

  

24。空参数删除

     

如果替换没有出现在双引号中,则从标量或数组元素中获取的任何零长度参数都会从插入到命令行的参数列表中消失。

     

--- 24. Empty argument removal, Rules, Expansion, zshparam(1)

@*

  

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

     

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

     

--- III SHELL PROGRAMMING QUESTIONS Q1, KSH-93 - Frequently Asked Questions

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

  

形式为[*][@]的下标计算为数组的所有元素;两者之间没有任何区别,只是它们出现在双引号中。

     

"$foo[*]"的值为"$foo[1] $foo[2] ...",而"$foo[@]"的值为"$foo[1]" "$foo[2]" ...

     

...

     

当数组参数引用为$name(不带下标)时,其结果为$name[*]

     

--- Array Subscripts, zshparam(1)

"$list"与其他人

如您所见,zsh已经很清楚了,它为我们提供了4个不同的选项。但是我认为ksh用户可以这样说:

"$list""${list}""$list[*]"可能意味着它将仅对$list的第一个元素执行某些操作(并加上{{1} },而不是列表/数组引用。


这是示例代码:

"[*]"

以下输出:

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"
}