为什么变量在循环外的循环内发生变化

时间:2012-10-10 12:43:46

标签: bash

我使用command | awk '{ print $1; }' | while read val ; do循环执行命令输出。最近我想计算总和,我在bash中发现了一些奇怪的行为:

test.txt的内容

100
200
300

test.sh的内容

sum='0'
cat test.txt | awk '{ print $1; }' | while read val ; do
        sum=`expr $sum + $val`
        echo "sum is now: $sum"
done

echo "FINAL SUM: $sum"

执行test.sh输出

sum is now: 100
sum is now: 300
sum is now: 600
FINAL SUM: 0

最终金额应该是600.我该怎么做才能解决这个问题?

4 个答案:

答案 0 :(得分:2)

原因是使用了cat,它产生了另一个子shell。这意味着sum变量在第二个子shell中递增,然后在循环结束时超出范围(并返回其先前的0值)。

尝试将循环更新为而不是使用cat

sum='0'
while read val ; do
        sum=`expr $sum + $val`
        echo "sum is now: $sum"
done < test.txt

echo "FINAL SUM: $sum"

如果你实际上不需要循环(即 - 如果你没有处理任何其他列/内容处理),你可以直接使用awk并存储它的值进入sum变量:

sum=`awk '{ sum += $1; } END { print sum }' test.txt`;

答案 1 :(得分:2)

不需要bash管。您可以使用awk

完成所有操作
awk '{sum+= $1; printf "The sum is now: %s\n", sum } END { print "FINAL SUM:", sum }' file.txt

结果:

The sum is now: 100
The sum is now: 300
The sum is now: 600
FINAL SUM: 600

答案 2 :(得分:2)

要扩展新家具的状态,但是在某种程度上你可以使用arbritary输入命令,而不仅仅是cat

sum='0' 
while read val ; do
     sum=`expr $sum + $val`
     echo "sum is now: $sum" 
done < <(cat test.txt | awk '{ print $1 }')
echo "FINAL SUM: $sum"

cat test.txt替换为输出所需输入的任何命令。

答案 3 :(得分:0)

这种奇怪的行为实际上是由bash管道引起的

引用Bash reference manual

  

管道中的每个命令都在其自己的子shell中执行

sum视为while循环中的局部变量,这就是当你离开while循环时,sum似乎没有设置的原因。

其他人提出的解决方案可以正常使用。