数组在bash脚本中消失

Dog*_*rld 5 arrays bash

我正在编写一个脚本来收集各种网络统计信息.我要做的是从netstat -i命令生成一些delta数据.

我正在使用以下bash代码收集所需的数据:

declare -a array
n=0
netstat -i | tail -n +3 | while read LINE; do
        echo "Setting array[$n] to $LINE"
        array[$n]=$LINE
        echo "array now have ${#array[@]} entries"
        let n=$n+1
done
echo "array now have ${#array[@]} entries"
Run Code Online (Sandbox Code Playgroud)

此命令的输出是:

Setting array[0] to eth0       1500 0   4946794      0      0 0       2522971      0      0      0 BMRU
array now have 1 entries
Setting array[1] to lo        16436 0     25059      0      0 0         25059      0      0      0 LRU
array now have 2 entries
Setting array[2] to vmnet1     1500 0         6      0      0 0          1126      0      0      0 BMRU
array now have 3 entries
Setting array[3] to vmnet8     1500 0       955      0      0 0          1054      0      0      0 BMRU
array now have 4 entries
Setting array[4] to wlan0      1500 0    613879      0      0 0        351194      0      0      0 BMU
array now have 5 entries
array now have 0 entries
Run Code Online (Sandbox Code Playgroud)

如你所见,数组实际上在while循环后消失了,我不明白为什么.

koj*_*iro 5

每次使用管道时,都会创建一个隐式子shell.当子shell终止时,它的变量也会终止.一个快速解决方法是不要管道read.您可以使用进程替换来完成上述操作:

while read LINE; do
        echo "Setting array[$n] to $LINE"
        array[$n]=$LINE
        echo "array now have ${#array[@]} entries"
        let n=$n+1
done < <(netstat -i | tail -n +3)
Run Code Online (Sandbox Code Playgroud)

更符合POSIX的方法(阅读:更具可移植性,更少基础)是让所有事情都发生在子shell中:

netstat -i | tail -n +3 | {
    declare -a array
    n=0
    while read LINE; do
        echo "Setting array[$n] to $LINE"
        array[$n]=$LINE
        echo "array now have ${#array[@]} entries"
        let n=$n+1
    done
    echo "array now have ${#array[@]} entries"
}
Run Code Online (Sandbox Code Playgroud)

你可以在Greg Wooledge的维基上阅读这个(以及更多)的优点.