Bash循环中的计数器递增不起作用

我有以下简单的脚本,我正在运行一个循环,并希望保持一个COUNTER 。 我无法弄清楚为什么柜台没有更新。 是由于subshel​​l创build? 我怎样才能解决这个问题?

 #!/bin/bash WFY_PATH=/var/log/nginx WFY_FILE=error.log COUNTER=0 grep 'GET /log_' $WFY_PATH/$WFY_FILE | grep 'upstream timed out' | awk -F ', ' '{print $2,$4,$0}' | awk '{print "http://domain.com"$5"&ip="$2"&date="$7"&time="$8"&end=1"}' | awk -F '&end=1' '{print $1"&end=1"}' | ( while read WFY_URL do echo $WFY_URL #Some more action COUNTER=$((COUNTER+1)) done ) echo $COUNTER # output = 0 

首先,你不增加柜台。 将COUNTER=$((COUNTER))改为COUNTER=$((COUNTER + 1))COUNTER=$[COUNTER + 1]会增加它。

其次,当你猜测的时候,将子shellvariables传回给被调用者是比较棘手的。 子shell中的variables在子shell之外是不可用的。 这些是subprocess本地的variables。

解决这个问题的一种方法是使用临时文件来存储中间值:

 TEMPFILE=/tmp/$$.tmp echo 0 > $TEMPFILE # Loop goes here # Fetch the value and increase it COUNTER=$[$(cat $TEMPFILE) + 1] # Store the new value echo $COUNTER > $TEMPFILE # Loop done, script done, delete the file unlink $TEMPFILE 
 COUNTER=1 while [ Your != "done" ] do echo " $COUNTER " COUNTER=$[$COUNTER +1] done 

testingBASH:CentOS,SuSE,RH

 COUNTER=$((COUNTER+1)) 

在现代编程中是相当笨拙的构造。

 (( COUNTER++ )) 

看起来更“现代”。 你也可以使用

 let COUNTER++ 

如果你认为这可以提高可读性。 有时,Bash提供了太多的处理方式 – 我认为Perl哲学 – 也许Python“只有一个正确的方法去做”可能更合适。 这是一个有争议的声明,如果有一个! 无论如何,我会build议(在这种情况下)的目的不仅仅是增加一个variables,而是(一般规则)也编写别人可以理解和支持的代码。 符合性要达到这个目标还有很长的路要走。

HTH

 count=0 base=1 (( count += base )) 

尝试使用

 COUNTER=$((COUNTER+1)) 

代替

 COUNTER=$((COUNTER)) 

我觉得这个awk调用和你的grep|grep|awk|awkpipe道相当:请testing一下。 你最后的awk命令看起来完全没有改变。

COUNTER的问题在于while循环在子shell中运行,所以当子shell退出时,对variables的任何更改都会消失。 你需要在同一个子shell中访问COUNTER的值。 或者采取@ DennisWilliamson的build议,使用一个stream程替代,并完全避免subshel​​l。

 awk ' /GET \/log_/ && /upstream timed out/ { split($0, a, ", ") split(a[2] FS a[4] FS $0, b) print "http://example.com" b[5] "&ip=" b[2] "&date=" b[7] "&time=" b[8] "&end=1" } ' | { while read WFY_URL do echo $WFY_URL #Some more action (( COUNTER++ )) done echo $COUNTER } 

而不是使用临时文件,可以避免使用进程replace在while循环周围创build子shell。

 while ... do ... done < <(grep ...) 

顺便说一句,你应该能够将所有的grep, grep, awk, awk, awk转换成一个awk

极简主义

 counter=0 ((counter++)) echo $counter 

这就是你需要做的一切:

 $((COUNTER++)) 

以下是学习bash Shell的第3版,第147,148页的摘录:

bash算术expression式相当于Java和C语言中的对应expression式[9]。 优先级和关联性与C相同。表6-2显示了所支持的算术运算符。 虽然其中一些是(或包含)特殊字符,但不需要反斜杠,因为它们在$((…))语法中。

……………………..

++和 – 操作符在你想增加或减less一个值时很有用[11]。 它们的工作方式与Java和C相同,例如, ++将值递增1 。 还有一个预先增量 :++ 。 以一个例子来certificate这个区别:

 $ i=0 $ echo $i 0 $ echo $((i++)) 0 $ echo $i 1 $ echo $((++i)) 2 $ echo $i 2 

http://www.safaribooksonline.com/a/learning-the-bash/7572399/

看来你没有更新counter是脚本,使用counter++