在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 00:33:31  来源:igfitidea点击:

Incrementing a variable inside a Bash loop

bashshellloops

提问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 USCOUNTERlooks 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 USCOUNTERin 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 ... varNwhere var1contains the first word in the line, $var2and so on, until $varNcontaining 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.

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 0because your while loopis 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"

-ccount

-c数数

([^ ]* )To detect a colonne

([^ ]* )检测冒号

{2}the colonne number

{2}冒号

USyour pattern

US你的模式