bash麻烦分配给一个循环中的数组索引

问题描述:

我可以得到这个在ksh中工作,但不是在bash中,这真的让我疯了。 希望这是明显的,我俯瞰。bash麻烦分配给一个循环中的数组索引

我需要运行一个外部命令,其中每行的输出将存储在数组索引处。

这个简化的例子看起来好像是在循环中正确地设置数组,但是在循环完成后,这些数组赋值都没有了?就好像这个循环被完全视为一个外壳一样?

junk.txt

this is a 
test to see 
if this works ok 

testa.sh

#!/bin/bash 

declare -i i=0 
declare -a array 

echo "Simple Test:" 
array[0]="hello" 
echo "array[0] = ${array[0]}" 

echo -e "\nLoop through junk.txt:" 
cat junk.txt | while read line 
do 
    array[i]="$line" 
    echo "array[$i] = ${array[i]}" 
    let i++ 
done 

echo -e "\nResults:" 
echo "  array[0] = ${array[0]}" 
echo " Total in array = ${#array[*]}" 
echo "The whole array:" 
echo ${array[@]} 

输出

Simple Test: 
array[0] = hello 

Loop through junk.txt: 
array[0] = this is a 
array[1] = test to see 
array[2] = if this works ok 

Results: 
     array[0] = hello 
Total in array = 1 
The whole array: 
hello 

因此,尽管在循环中,我们分配阵列[i]和所述回声进行验证。 但循环后,我回到阵列[0]包含“你好”没有其他元素。

bash 3,4和不同平台上的结果相同。

因为while循环处于管道中,所以循环体中的所有变量赋值都是执行循环的子shell的局部变量。 (我相信ksh不运行在一个子shell命令,这就是为什么你在bash有问题。)而是执行此操作:

while read line 
do 
    array[i]="$line" 
    echo "array[$i] = ${array[i]}" 
    let i++ 
done < junk.txt 

很少,如果有的话,你想用cat来管一单个文件到另一个命令;改用输入重定向。

更新:因为你需要从一个命令,而不是运行文件,另一个选项(如果可用)的进程替换:

while read line; do 
... 
done < <(command args ...) 

如果进程替换不可用,则需要输出到临时文件并重定向来自该文件的输入。

如果你正在使用bash 4.2或更高版本,您可以在循环之前执行这两个命令,和原来的管道进入半实物会的工作,因为while循环是在管道中的最后命令。

set +m # Turn off job control; it's probably already off in a non-interactive script 
shopt -s lastpipe 
cat junk.txt | while read line; do ...; done 

更新2:下面是基于user1596414的评论

array[0]=hello 
IFS=$'\n' array+=($(command)) 

一个环路更少溶液的命令的输出被分成仅基于换行符基于词语(使得每一行是一个单独的字),并将生成的每插槽数组添加到原始数组中。如果您仅使用循环来构建数组,这非常好。它也可能被修改以适应少量的每行处理,这与Python列表理解模式相似。

+0

“我需要运行一个外部命令,其中输出的每一行都将存储在数组索引处。” “猫”是一个简单的例子。我需要运行一个命令,并将其输出到循环中,并像 user1596414 2012-08-13 21:07:10

+0

更新了几个选项。最后一个(如果你的bash版本足够新)可能是你想要的。 – chepner 2012-08-13 21:21:23

+1

+1临时文件或bash 4.2(或更高版本)选项可以工作。有第三个选项使用IFS来处理空白,如果不需要遍历输出,也可以与简单的数组赋值相结合。 – user1596414 2012-08-13 22:11:44