bash脚本和zsh shell中的数组行为(开始索引0还是1?)

时间:2022-07-26 15:42:08

I need explenation about the following behavior of arrays in shell scripting:

我需要解释一下shell脚本中数组的以下行为:

Imagine the following is given:

假设给出以下内容:

arber@host ~> ls
fileA fileB script.sh

Now i can do the following commands:

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

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

But when I do this via script.sh it behaves different (Start Index = 0):

但是当我通过脚本做这个的时候。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

Here the result:

这里的结果:

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

I use Ubuntu 18.04 LTS and zsh. Can someone explain this?

我使用Ubuntu 18.04 LTS和zsh。有人能解释一下这个吗?

1 个解决方案

#1


3  

Arrays in Bash are indexed from zero, and in zsh they're indexed from one.

Bash中的数组从0被索引,在zsh中它们从1被索引。

But you don't need the indices for a simple use case such as this. Looping over ${array[@]} works in both:

但是,对于这样的简单用例,不需要索引。对${array[@]}的循环作用在以下两种情况中:

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

In zsh you could also use $files instead of "${files[@]}", but that doesn't work in Bash. (And there's the slight difference that it drops empty array elements, but you won't get any from file names.)

在zsh中,您也可以使用$files而不是“${files[@]}”,但这在Bash中是行不通的。(不同之处在于,它会删除空数组元素,但不会从文件名中获得任何元素。)


Also, don't use $(ls file*), it will break if you have filenames with spaces (see WordSpliting on BashGuide), and is completely useless to begin with.

另外,不要使用$(ls文件*),如果您有带空格的文件名(请参阅BashGuide中的WordSpliting),它将会崩溃,而且从一开始就完全没用。

The shell is perfectly capable of generating filenames by itself. That's actually what will happen there, the shell finds all files with names matching file*, passes them to ls, and ls just prints them out again for the shell to read and process.

shell完全能够自己生成文件名。这就是将在那里发生的事情,shell找到所有名称匹配的文件*,将它们传递给ls, ls将它们再次打印出来,以便shell读取和处理。

#1


3  

Arrays in Bash are indexed from zero, and in zsh they're indexed from one.

Bash中的数组从0被索引,在zsh中它们从1被索引。

But you don't need the indices for a simple use case such as this. Looping over ${array[@]} works in both:

但是,对于这样的简单用例,不需要索引。对${array[@]}的循环作用在以下两种情况中:

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

In zsh you could also use $files instead of "${files[@]}", but that doesn't work in Bash. (And there's the slight difference that it drops empty array elements, but you won't get any from file names.)

在zsh中,您也可以使用$files而不是“${files[@]}”,但这在Bash中是行不通的。(不同之处在于,它会删除空数组元素,但不会从文件名中获得任何元素。)


Also, don't use $(ls file*), it will break if you have filenames with spaces (see WordSpliting on BashGuide), and is completely useless to begin with.

另外,不要使用$(ls文件*),如果您有带空格的文件名(请参阅BashGuide中的WordSpliting),它将会崩溃,而且从一开始就完全没用。

The shell is perfectly capable of generating filenames by itself. That's actually what will happen there, the shell finds all files with names matching file*, passes them to ls, and ls just prints them out again for the shell to read and process.

shell完全能够自己生成文件名。这就是将在那里发生的事情,shell找到所有名称匹配的文件*,将它们传递给ls, ls将它们再次打印出来,以便shell读取和处理。