Bash循环中的计数器递增不起作用
我有以下简单的脚本,我正在运行一个循环,并希望保持一个COUNTER
。 我无法弄清楚为什么柜台没有更新。 是由于subshell创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|awk
pipe道相当:请testing一下。 你最后的awk命令看起来完全没有改变。
COUNTER的问题在于while循环在子shell中运行,所以当子shell退出时,对variables的任何更改都会消失。 你需要在同一个子shell中访问COUNTER的值。 或者采取@ DennisWilliamson的build议,使用一个stream程替代,并完全避免subshell。
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++