Arb*_*ber 5 linux bash shell ubuntu zsh
我需要对shell脚本中数组的以下行为进行解释:
想象一下,给出了以下内容:
arber@host ~> ls
fileA fileB script.sh
Run Code Online (Sandbox Code Playgroud)
现在,我可以执行以下命令:
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
Run Code Online (Sandbox Code Playgroud)
但是当我通过script.sh执行此操作时,它的行为有所不同(开始索引= 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
Run Code Online (Sandbox Code Playgroud)
结果如下:
arber@host ~> ./script.sh
fileA
fileB
Run Code Online (Sandbox Code Playgroud)
我使用Ubuntu 18.04 LTS和zsh。有人可以解释吗?
Tom*_*ale 17
bash数组索引从0(总是)开始zsh数组索引开始于1(除非设置了选项KSH_ARRAYS)要始终获得一致的行为,请使用:
${array[@]:offset:length}
Run Code Online (Sandbox Code Playgroud)
对于同时适用于bash和 的代码zsh,您需要使用offset:length语法而不是[subscript]语法。
即使对于zsh-only 代码,您仍然需要这样做(或使用emulate -LR zsh),因为zsh的数组下标基础由KSH_ARRAYS选项决定。
例如,要引用数组中的第一个元素:
${array[@]:0:1}
Run Code Online (Sandbox Code Playgroud)
这里,array[@]是所有元素,0是偏移量(总是从 0 开始),1是所需元素的数量。
Bash中的数组从零开始索引,而zsh中的数组从1开始索引。
但您不需要像这样的简单用例的索引。循环${array[@]}工作在两个方面:
files=(file*)
for f in "${files[@]}"; do
echo "$f"
done
Run Code Online (Sandbox Code Playgroud)
在zsh中,您也可以使用$files代替"${files[@]}",但这在Bash中不起作用。(并且有一点点区别,它删除了空数组元素,但文件名中没有任何内容。)
另外,$(ls file*)如果文件名带有空格(请参见BashGuide上的WordSpliting),请不要使用,它会中断,并且一开始是完全没有用的。
Shell完全能够自己生成文件名。那实际上就是在那里发生的事情,shell查找所有名称匹配的文件file*,将它们传递给ls,然后ls再次将它们打印出来以供shell读取和处理。