linux bash脚本和zsh shell中数组的行为(起始索引0或1?)

5ssjco0h  于 12个月前  发布在  Linux
关注(0)|答案(2)|浏览(164)

我需要解释shell脚本中数组的以下行为:
假设给出以下内容:

arber@host ~> ls
fileA fileB script.sh

现在我可以执行以下命令:

arber@host ~> ARR=($(ls -d file*))
arber@host ~> echo ${ARR[0]}          # start index 0

arber@host ~> echo ${ARR[1]}          # start index 1
fileA
arber@host ~> echo ${ARR[2]}          # start index 2
fileB

但是当我通过script.sh执行此操作时,它的行为不同(Start Index = 0):

arber@host ~> cat script.sh
#!/bin/bash
ARR=($(ls -d file*))

# get length of an array
aLen=${#ARR[@]}

# use for loop read all items (START INDEX 0)
for (( i=0; i<${aLen}; i++ ));
do
  echo ${ARR[$i]}
done

结果如下:

arber@host ~> ./script.sh
fileA
fileB

Ubuntu 18.04 LTS和zsh。有人能解释一下吗?

nhaq1z21

nhaq1z211#

TL;DR:

  • bash数组索引从0开始(始终)
  • zsh数组索引从1开始(除非设置了KSH_ARRAYS选项)
    要始终获得一致的行为,请使用:用途:
${array[@]:offset:length}

说明

对于同时在bashzsh中工作的代码,您需要使用offset:length语法而不是[subscript]语法。
即使对于仅限zsh的代码,您仍然需要这样做(或使用emulate -LR zsh),因为zsh的数组下标基础由KSH_ARRAYS选项确定。
例如,引用数组中的第一个元素:

${array[@]:0:1}

这里,array[@]是所有元素,0是偏移量(总是基于0),1是所需元素的数量。

xqk2d5yq

xqk2d5yq2#

Arrays in Bash are indexed from zero,在zsh中它们是从1开始索引的。
但是对于这样的简单用例,您不需要索引。在${array[@]}上循环在以下两种情况下都有效:

files=(file*)
for f in "${files[@]}"; do
    echo "$f"
done

在zsh中,你也可以使用$files来代替"${files[@]}",但这在Bash中不起作用。(还有一个细微的区别,它删除了空数组元素,但你不会从文件名中得到任何元素。
另外,不要使用$(ls file*),如果你的文件名中有空格,它会崩溃(参见WordSpliting on BashGuide),而且开始时完全没用。
shell完全能够自己生成文件名。这实际上就是在那里发生的事情,shell找到所有名称匹配file*的文件,将它们传递给lsls只是再次打印出来供shell读取和处理。

相关问题