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

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

我尝试用下面的方式在 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[@]}"

出了什么问题,为什么循环结束后我得到空数组?

答案1

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

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

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

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

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

mapfile -t ring < <(ls -las | tail -n +4)

答案2

这应该可以正常工作:

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

来源:http://wiki.bash-hackers.org/syntax/arrays

答案3

原因是 while 循环是在子 shell 中执行的,因为它是通过管道传输的。 Subshel​​l 使用父 shell 环境的副本,并且当子 shell 退出时不会将其传回。

对于 bash,您可以使用命令分组解决方法,请注意添加了大括号

ls -las | tail -n +4 | { while read line;  do  ring+=("$line");  echo ${ring[-1]};  done;  echo ${ring[0]}; }

相关内容