2014-10-01 40 views
0

我有一个非常简单的bash脚本来计算出现在文件的每一行的数字总和(我知道有这样做的更好的方法,但我实际上需要这个总和作为辅助信息,脚本应该是更多的东西稍后的)。脚本如下:为什么变量值在bash中终止循环后会丢失?

TOTAL=0; 
cat $DATAFILE | while read LINE; 
do 
     COUNT=`echo $LINE| awk '{print $2;}'`; 
     TOTAL=$((TOTAL+COUNT)); 
done 
echo "Total = $TOTAL"; 

但是,我总是得到输出“Total = 0”。令人惊讶的是,如果我移动while循环内的最后一行,我会得到正确的结果。例如,如果输入文件包含

A 5 
B 3 
C 6 

我得到的输出

Total = 5 
Total = 8 
Total = 14 

但目前的版本总是输出0似乎分配给总变量值莫名其妙丢失。

任何人都可以帮我解决这个问题吗?

在此先感谢

+1

由于在管道完成时管道的右侧会退出,除非您有'shopt -s lastpipe'活动。 – 2014-10-01 14:46:32

+2

[我在管道中的循环中设置变量。为什么它们在循环终止后消失?或者,为什么我不能通过管道数据读取?](http://mywiki.wooledge.org/BashFAQ/024) – fedorqui 2014-10-01 14:49:24

回答

5

这是BashFAQ #24。幸运的是,由于不必要地使用了cat,你只能在这里触碰它 - 你根本没有理由使用管线。


管道的右手边(如对其内容的其余部分,而由短暂的外层以内),当管做,除非你有shopt -s lastpipe主动退出。

相反,无论是添加一行:

shopt -s lastpipe 

或调整你的循环:

while read LINE; 
do 
     COUNT=`echo $LINE| awk '{print $2;}'`; 
     TOTAL=$((TOTAL+COUNT)); 
done <"$DATAFILE" 

...或者,在一个情况下,你真的需要管道从另一个进程,使用过程替换:

while read LINE; 
do 
     COUNT=`echo $LINE| awk '{print $2;}'`; 
     TOTAL=$((TOTAL+COUNT)); 
done < <(cat "$DATAFILE") 

顺便说一句,如果你的sheba NG是#!/bin/bash,不#!/bin/sh,这将更好的写法如下:

total=0 
while read -r _ count do; 
    ((total += count)) 
done <"$DATAFILE" 

read可以IFS本身上的字符分割线 - 你不需要使用awk了点。

按照惯例,变量名应该是全小写的,除非它们代表环境变量或shell内建函数。

+3

这里的重要信息是管道的每个部分都在子外壳中执行。这意味着'while'循环在不同的BASH中执行,终止 - >所有变量都随之死亡。 – 2014-10-01 14:49:11

相关问题