在 Bash 循环中递增变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20681210/
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
Incrementing a variable inside a Bash loop
提问by maephisto
I'm trying to write a small script that will count entries in a log file, and I'm incrementing a variable (USCOUNTER
) which I'm trying to use after the loop is done.
我正在尝试编写一个小脚本来计算日志文件中的条目,并且我正在增加一个变量 ( USCOUNTER
),我在循环完成后尝试使用该变量。
But at that moment USCOUNTER
looks to be 0 instead of the actual value. Any idea what I'm doing wrong? Thanks!
但在那一刻USCOUNTER
看起来是 0 而不是实际值。知道我做错了什么吗?谢谢!
FILE=
tail -n10 mylog > $FILE
USCOUNTER=0
cat $FILE | while read line; do
country=$(echo "$line" | cut -d' ' -f1)
if [ "US" = "$country" ]; then
USCOUNTER=`expr $USCOUNTER + 1`
echo "US counter $USCOUNTER"
fi
done
echo "final $USCOUNTER"
It outputs:
它输出:
US counter 1
US counter 2
US counter 3
..
final 0
回答by fedorqui 'SO stop harming'
You are using USCOUNTER
in a subshell, that's why the variable is not showing in the main shell.
您USCOUNTER
在子 shell中使用,这就是变量未显示在主 shell 中的原因。
Instead of cat FILE | while ...
, do just a while ... done < $FILE
. This way, you avoid the common problem of I set variables in a loop that's in a pipeline. Why do they disappear after the loop terminates? Or, why can't I pipe data to read?:
而不是cat FILE | while ...
,只做一个while ... done < $FILE
. 这样,您就可以避免我在管道中的循环中设置变量的常见问题。为什么它们在循环终止后消失?或者,为什么我不能通过管道读取数据?:
while read country _; do
if [ "US" = "$country" ]; then
USCOUNTER=$(expr $USCOUNTER + 1)
echo "US counter $USCOUNTER"
fi
done < "$FILE"
Note I also replaced the `` expression with a $().
注意我还用 $() 替换了 `` 表达式。
I also replaced while read line; do country=$(echo "$line" | cut -d' ' -f1)
with while read country _
. This allows you to say while read var1 var2 ... varN
where var1
contains the first word in the line, $var2
and so on, until $varN
containing the remaining content.
我也换成while read line; do country=$(echo "$line" | cut -d' ' -f1)
了while read country _
。这使您可以说while read var1 var2 ... varN
在那里var1
包含在该行的第一个字,$var2
等等,直到$varN
包含剩余的内容。
回答by Aleks-Daniel Jakimenko-A.
- Always use
-r
with read. - There is no need to use
cut
, you can stick with pure bash solutions.- In this case passing
read
a 2nd var (_
) to catch the additional "fields"
- In this case passing
- Prefer
[[ ]]
over[ ]
. - Use arithmetic expressions.
- Do not forget to quote variables! Link includes other pitfalls as well
- 始终
-r
与 read 一起使用。 - 无需使用
cut
,您可以坚持使用纯 bash 解决方案。- 在这种情况下,传递
read
第二个 var (_
) 以捕获额外的“字段”
- 在这种情况下,传递
- 身高
[[ ]]
超过[ ]
。 - 使用算术表达式。
- 不要忘记引用变量!链接还包括其他陷阱
while read -r country _; do
if [[ $country = 'US' ]]; then
((USCOUNTER++))
echo "US counter $USCOUNTER"
fi
done < "$FILE"
回答by geekzspot
minimalist
极简主义者
counter=0
((counter++))
echo $counter
回答by anubhava
You're getting final 0
because your while loop
is being executed in a sub (shell) process and any changes made there are not reflected in the current (parent) shell.
你得到final 0
是因为你while loop
正在一个子(shell)进程中执行,并且在那里所做的任何更改都没有反映在当前(父)shell中。
Correct script:
正确的脚本:
while read -r country _; do
if [ "US" = "$country" ]; then
((USCOUNTER++))
echo "US counter $USCOUNTER"
fi
done < "$FILE"
回答by jobwat
I had the same $count variable in a while loop getting lost issue.
我在 while 循环丢失问题中有相同的 $count 变量。
@fedorqui's answer(and a few others) are accurate answers to the actual question: the sub-shell is indeed the problem.
@fedorqui 的答案(以及其他一些答案)是对实际问题的准确答案:子外壳确实是问题所在。
But it lead me to another issue: I wasn't piping a file content... but the output of a series of pipes & greps...
但这让我想到了另一个问题:我不是在通过管道传输文件内容......而是一系列管道和 grep 的输出......
my erroring sample code:
我的错误示例代码:
count=0
cat /etc/hosts | head | while read line; do
((count++))
echo $count $line
done
echo $count
and my fix thanks to the help of this thread and the process substitution:
多亏了这个线程和进程替换的帮助,我的修复:
count=0
while IFS= read -r line; do
((count++))
echo "$count $line"
done < <(cat /etc/hosts | head)
echo "$count"
回答by Walter A
USCOUNTER=$(grep -c "^US " "$FILE")
回答by thanh
Using the following 1 line command for changing many files name in linux using phrase specificity:
使用以下 1 行命令使用短语特异性更改 linux 中的许多文件名:
find -type f -name '*.jpg' | rename 's/holiday/honeymoon/'
For all files with the extension ".jpg", if they contain the string "holiday", replace it with "honeymoon". For instance, this command would rename the file "ourholiday001.jpg" to "ourhoneymoon001.jpg".
对于所有扩展名为“.jpg”的文件,如果它们包含字符串“holiday”,请将其替换为“honeymoon”。例如,此命令会将文件“ourholiday001.jpg”重命名为“ourhoneymoon001.jpg”。
This example also illustrates how to use the find command to send a list of files (-type f) with the extension .jpg (-name '*.jpg') to rename via a pipe (|). rename then reads its file list from standard input.
此示例还说明了如何使用 find 命令发送扩展名为 .jpg (-name '*.jpg') 的文件列表 (-type f) 以通过管道 (|) 重命名。rename 然后从标准输入读取它的文件列表。
回答by trax
Incrementing a variable can be done like that:
增加一个变量可以这样完成:
_my_counter=$[$_my_counter + 1]
Counting the number of occurrence of a pattern in a column can be done with grep
可以使用 grep 计算列中模式出现的次数
grep -cE "^([^ ]* ){2}US"
-c
count
-c
数数
([^ ]* )
To detect a colonne
([^ ]* )
检测冒号
{2}
the colonne number
{2}
冒号
US
your pattern
US
你的模式