为什么while循环后数组为空?

Dim*_*maf 7 shell bash pipe variable

我尝试在 bash-4.2 中初始化一个数组:

ring=()
ls -las | tail -n +4 | while read line
> do
> ring+=("$line")
> echo ${ring[-1]}
> done
3924 -rw-r--r-- 1 username group 4015716 Mar 23 15:14 script.jar
4 -rw-r--r-- 1 username group 9 Feb 29 12:40 rec.lst
5541 -rw-r--r-- 1 username group 5674226917 Mar 28 15:25 debug.out
8 -rw-r--r-- 1 username group 6135 Mar 25 12:16 script.class
8 -rw-r--r-- 1 username group 6377 Mar 25 11:57 script.java
8 -rwxr-xr-x 1 username group 4930 Mar 8 15:21 script-0.0.0.sh
8 -rwxr-xr-x 1 username group 6361 Mar 28 15:27 script-0.0.1.sh
echo ${ring[0]}

echo "${ring[0]}"

echo "${ring[@]}"
Run Code Online (Sandbox Code Playgroud)

怎么了,为什么我在循环结束后得到空数组?

Rea*_*tic 13

您的问题是在管道 ( command1 | command2 | command3 ...) 中,命令是在子 shell 中运行的。变量在子外壳之间或子外壳和主外壳之间不共享。该ringwhile循环比不同ring主壳。

克服这个问题的一种方法是使用进程替换:

while read line;  do  ring+=("$line");  echo ${ring[-1]};  done < <(ls -las|tail -n +4) 
Run Code Online (Sandbox Code Playgroud)

<(command)语法称为进程替换,并将命令的输出重定向到命名管道。然后使用熟悉的重定向,<就好像它是一个文件一样。使用时<,没有子shell,因此ring将设置变量。

请注意,有一个 shell 内置命令可以从文件的行中填充数组:

mapfile -t ring < <(ls -las | tail -n +4)
Run Code Online (Sandbox Code Playgroud)