我需要解释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。有人能解释一下吗?
2条答案
按热度按时间nhaq1z211#
TL;DR:
bash
数组索引从0
开始(始终)zsh
数组索引从1
开始(除非设置了KSH_ARRAYS
选项)要始终获得一致的行为,请使用:用途:
说明
对于同时在
bash
和zsh
中工作的代码,您需要使用offset:length
语法而不是[subscript]
语法。即使对于仅限
zsh
的代码,您仍然需要这样做(或使用emulate -LR zsh
),因为zsh
的数组下标基础由KSH_ARRAYS
选项确定。例如,引用数组中的第一个元素:
这里,
array[@]
是所有元素,0
是偏移量(总是基于0),1
是所需元素的数量。xqk2d5yq2#
Arrays in Bash are indexed from zero,在zsh中它们是从1开始索引的。
但是对于这样的简单用例,您不需要索引。在
${array[@]}
上循环在以下两种情况下都有效:在zsh中,你也可以使用
$files
来代替"${files[@]}"
,但这在Bash中不起作用。(还有一个细微的区别,它删除了空数组元素,但你不会从文件名中得到任何元素。另外,不要使用
$(ls file*)
,如果你的文件名中有空格,它会崩溃(参见WordSpliting on BashGuide),而且开始时完全没用。shell完全能够自己生成文件名。这实际上就是在那里发生的事情,shell找到所有名称匹配
file*
的文件,将它们传递给ls
,ls
只是再次打印出来供shell读取和处理。