1

我使用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

4 回答 4

2

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

尝试更新您的循环以使用cat

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

echo "FINAL SUM: $sum"

If you don't actually need the loop (i.e. - if you're not handling any other column/content-processing), you could use awk directly and store it's value into the sum variable:

sum=`awk '{ sum += $1; } END { print sum }' test.txt`;
于 2012-10-10T12:50:46.983 回答
2

There's no need for the bash pipe. You can do it all with awk:

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

Results:

The sum is now: 100
The sum is now: 300
The sum is now: 600
FINAL SUM: 600
于 2012-10-10T12:53:49.040 回答
2

To expand on what newfurniturey states, but in a way where you can use it with an arbritary input command, not just 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"

Replace cat test.txt with whatever command which outputs the input you require.

于 2012-10-10T13:00:49.440 回答
0

This strange behaviour is actually caused by the bash pipes

To quote the Bash reference manual

Each command in a pipeline is executed in its own subshell

Think of sum as a local variable in your while loop, that's why sum appears not to be set when you go out of the while-loop.

The solutions proposed by the others will work fine.

于 2012-10-15T13:35:01.443 回答