为什么我的Bash计数器在while循环之后重置

我有一个Bash脚本,我想要统计在循环一个文件时做了多less事情。 计数似乎在循环内工作,但在此之后,variables似乎重置。

nKeys=0 cat afile | while read -r line do #...do stuff let nKeys=nKeys+1 # this will print 1,2,..., etc as expected echo Done entry $nKeys done # PROBLEM: this always prints "... 0 keys" echo Finished writing $destFile, $nKeys keys 

以上的输出是单独的行:

完成条目1
完成条目2
写完/写,0键

我想要的输出是:

完成条目1
完成条目2
完成的写作/等等,2个键

我不太清楚为什么nKeys在循环后为0 :(我认为这是一些基本的,但该死的,如果我可以发现它尽pipe看http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html和其他资源。

手指穿过其他人可以看看它,并“去吧!你必须…”!

在刚刚发布的Bash 4.2中,你可以这样做来防止创build一个子shell:

 shopt -s lastpipe 

另外,正如你可能在Ignacio提供的链接中看到的,你有一个无用的cat

 while read -r line do ... done < afile 

正如在接受的答案中提到的,这是因为pipe道产生了单独的subprocess。 为了避免这种情况, command grouping一直是我的最佳select。 也就是说,在子shell中的pipe道之后做所有事情。

 nKeys=0 cat afile | { while read -r line do #...do stuff let nKeys=nKeys+1 # this will print 1,2,..., etc as expected echo Done entry $nKeys done # PROBLEM: this always prints "... 0 keys" echo Finished writing $destFile, $nKeys keys } 

现在它会正确报告$nKeys的值(即你想要的)。

我以下面的方式达到了预期的效果,而不使用pipe道或文件

 #!/bin/sh counter=0 string="apple orange mango egg indian" str_len=${#string} while [ $str_len -ne 0 ] do c=${string:0:1} if [[ "$c" = [aeiou] ]] then echo -n "vowel : " echo "- $c" counter=$(( $counter + 1 )) fi string=${string:1} str_len=${#string} done printf "The number of vowels in the given string are : %s "$counter echo