Linux Bash循环中的计数器增量不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10515964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Counter increment in Bash loop not working
提问by Sparsh Gupta
I have the following simple script where I am running a loop and want to maintain a COUNTER
. I am unable to figure out why the counter is not updating. Is it due to subshell thats getting created? How can I potentially fix this?
我有以下简单的脚本,我在其中运行一个循环并希望维护一个COUNTER
. 我无法弄清楚为什么计数器没有更新。是因为创建了子shell吗?我怎样才能解决这个问题?
#!/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 ,,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
}' | awk '{print "http://domain.com""&ip=""&date=""&time=""&end=1"}' | awk -F '&end=1' '{print "&end=1"}' |
(
while read WFY_URL
do
echo $WFY_URL #Some more action
COUNTER=$((COUNTER+1))
done
)
echo $COUNTER # output = 0
采纳答案by bos
First, you are not increasing the counter. Changing COUNTER=$((COUNTER))
into COUNTER=$((COUNTER + 1))
or COUNTER=$[COUNTER + 1]
will increase it.
首先,您没有增加计数器。更改COUNTER=$((COUNTER))
为COUNTER=$((COUNTER + 1))
或COUNTER=$[COUNTER + 1]
将增加它。
Second, it's trickier to back-propagate subshell variables to the callee as you surmise. Variables in a subshell are not available outside the subshell. These are variables local to the child process.
其次,正如您猜测的那样,将子shell 变量反向传播到被调用者会更棘手。子外壳中的变量在子外壳之外不可用。这些是子进程的局部变量。
One way to solve it is using a temp file for storing the intermediate value:
解决它的一种方法是使用临时文件来存储中间值:
COUNTER=$((COUNTER+1))
回答by dbf
Try to use
尝试使用
COUNTER=$((COUNTER))
instead of
代替
while ...
do
...
done < <(grep ...)
回答by yjshen
It seems that you didn't update the counter
is the script, use counter++
看来你没有更新counter
是脚本,使用counter++
回答by Paused until further notice.
Instead of using a temporary file, you can avoid creating a subshell around the while
loop by using process substitution.
您可以while
通过使用进程替换来避免在循环周围创建子shell,而不是使用临时文件。
bash -c 'echo foo | while read -r s; do c=3; done; echo "$c"'
bash -c 'shopt -s lastpipe; echo foo | while read -r s; do c=3; done; echo "$c"'
3
By the way, you should be able to transform all that grep, grep, awk, awk, awk
into a single awk
.
顺便说一句,您应该能够将所有这些grep, grep, awk, awk, awk
转换为单个awk
.
Starting with Bash 4.2, there is a lastpipe
option that
从 Bash 4.2 开始,有一个lastpipe
选项
runs the last command of a pipeline in the current shell context. The lastpipe option has no effect if job control is enabled.
在当前 shell 上下文中运行管道的最后一个命令。如果启用了作业控制,则 lastpipe 选项无效。
awk '
/GET \/log_/ && /upstream timed out/ {
split(COUNTER=1
while [ Your != "done" ]
do
echo " $COUNTER "
COUNTER=$[$COUNTER +1]
done
, a, ", ")
split(a[2] FS a[4] FS count=0
base=1
(( count += base ))
, 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
}
回答by glenn Hymanman
I think this single awk call is equivalent to your grep|grep|awk|awk
pipeline: please test it. Your last awk command appears to change nothing at all.
我认为这个单一的 awk 调用相当于您的grep|grep|awk|awk
管道:请测试它。您的最后一个 awk 命令似乎没有任何改变。
The problem with COUNTER is that the while loop is running in a subshell, so any changes to the variable vanish when the subshell exits. You need to access the value of COUNTER in that same subshell. Or take @DennisWilliamson's advice, use a process substitution, and avoid the subshell altogether.
COUNTER 的问题在于while 循环在子shell 中运行,因此当子shell 退出时,对变量的任何更改都会消失。您需要在同一个子 shell 中访问 COUNTER 的值。或者接受@DennisWilliamson 的建议,使用进程替换,并完全避免使用子shell。
COUNTER=$((COUNTER+1))
回答by Jay Stan
(( COUNTER++ ))
TESTED BASH: Centos, SuSE, RH
测试 BASH:Centos、SuSE、RH
回答by pkm
let COUNTER++
回答by Bill Parker
counter=0
((counter++))
echo $counter
is quite a clumsy construct in modern programming.
在现代编程中是一个相当笨拙的结构。
$((COUNTER++))
looks more "modern". You can also use
看起来更“现代”。你也可以使用
$ i=0
$ echo $i
0
$ echo $((i++))
0
$ echo $i
1
$ echo $((++i))
2
$ echo $i
2
if you think that improves readability. Sometimes, Bash gives too many ways of doing things - Perl philosophy I suppose - when perhaps the Python "there is only one right way to do it" might be more appropriate. That's a debatable statement if ever there was one! Anyway, I would suggest the aim (in this case) is not just to increment a variable but (general rule) to also write code that someone else can understand and support. Conformity goes a long way to achieving that.
如果您认为这可以提高可读性。有时,Bash 提供了太多的做事方式——我想是 Perl 哲学——也许 Python “只有一种正确的方法可以做到这一点”可能更合适。如果有的话,这是一个值得商榷的声明!无论如何,我建议目标(在这种情况下)不仅仅是增加一个变量,而是(一般规则)还要编写其他人可以理解和支持的代码。一致性对实现这一目标大有帮助。
HTH
HTH
回答by geekzspot
minimalist
极简主义者
##代码##回答by C.E. Montijo
This is all you need to do:
这就是您需要做的所有事情:
##代码##Here's an excerpt from Learning the bash Shell, 3rd Edition, pp. 147, 148:
以下是Learning the bash Shell,第 3 版,第 147、148 页的摘录:
basharithmetic expressions are equivalent to their counterparts in the Java and C languages.[9] Precedence and associativity are the same as in C. Table 6-2 shows the arithmetic operators that are supported. Although some of these are (or contain) special characters, there is no need to backslash-escape them, because they are within the $((...)) syntax.
bash算术表达式等效于它们在 Java 和 C 语言中的对应项。 [9] 优先级和结合性与 C 中的相同。表 6-2 显示了支持的算术运算符。尽管其中一些是(或包含)特殊字符,但不需要反斜杠转义它们,因为它们在 $((...)) 语法中。
..........................
......................................
The ++ and - operators are useful when you want to increment or decrement a value by one.[11] They work the same as in Java and C, e.g., value++ increments value by 1. This is called post-increment; there is also a pre-increment: ++value. The difference becomes evident with an example:
##代码##++ 和 - 运算符在您希望将值递增或递减 1 时很有用。 [11] 它们的工作方式与 Java 和 C 中的相同,例如,value++ 将 value 增加 1。这称为post-increment;还有一个预增量:++值。举个例子,区别就很明显了:
See http://www.safaribooksonline.com/a/learning-the-bash/7572399/
见http://www.safaribooksonline.com/a/learning-the-bash/7572399/