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

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
于 2012-10-10T12:53:49.040 に答える
2

原因は、cat別のサブシェルを生成する の使用です。これは、変数が 2 番目のサブシェルでインクリメントされ、ループが終了したとき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"

実際にループが必要ない場合(つまり、他の列/コンテンツ処理を処理していない場合)、直接使用してその値を変数awkに格納できます。sum

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

newfurniturey の状態を拡張するには、次のように任意の入力コマンドで使用できるようにします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必要な入力を出力するコマンドに置き換えます。

于 2012-10-10T13:00:49.440 に答える
0

この奇妙な動作は、実際には bash パイプが原因です

Bashリファレンスマニュアルを引用するには

パイプライン内の各コマンドは、独自のサブシェルで実行されます

sumwhile ループのローカル変数と考えてください。そのため、while ループsumから抜けたときに設定されていないように見えます。

他の人が提案した解決策はうまくいきます。

于 2012-10-15T13:35:01.443 に答える