增加Bash循环内的变量

时间:2013-12-19 11:58:08

标签: bash shell loops

我正在尝试编写一个小脚本来计算日志文件中的条目,并且我正在递增一个变量(USCOUNTER),我在循环完成后尝试使用它。

但在那一刻USCOUNTER看起来是0而不是实际值。知道我做错了什么吗?谢谢!

FILE=$1

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"

输出:

US counter 1
US counter 2
US counter 3
..
final 0

8 个答案:

答案 0 :(得分:42)

您在子shell中使用USCOUNTER,这就是变量未在主shell中显示的原因。

而不是cat FILE | while ...,而只需while ... done < $FILE。这样,您可以避免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?

的常见问题
while read country _; do
  if [ "US" = "$country" ]; then
        USCOUNTER=$(expr $USCOUNTER + 1)
        echo "US counter $USCOUNTER"
  fi
done < "$FILE"

注意我也用$()替换了``表达式。

我还将while read line; do country=$(echo "$line" | cut -d' ' -f1)替换为while read country _。这样您就可以说while read var1 var2 ... varN其中var1包含行中的第一个单词$var2,依此类推,直到$varN包含剩余内容。

答案 1 :(得分:22)

while read -r country _; do
  if [[ $country = 'US' ]]; then
    ((USCOUNTER++))
    echo "US counter $USCOUNTER"
  fi
done < "$FILE"

答案 2 :(得分:12)

您将获得final 0,因为您的while loop正在子(shell)进程中执行,并且所做的任何更改都不会反映在当前(父)shell中。

正确的脚本:

while read -r country _; do
  if [ "US" = "$country" ]; then
        ((USCOUNTER++))
        echo "US counter $USCOUNTER"
  fi
done < "$FILE"

答案 3 :(得分:12)

极简

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

答案 4 :(得分:6)

我在while循环中遇到了丢失问题的同一$ count变量。

@fedorqui's answer(以及其他几个)是对实际问题的准确答案:子shell确实是问题。

但它引出了另一个问题:我没有管道文​​件内容......但是输出了一系列管道和输出。里grep ...

我的错误示​​例代码:

count=0
cat /etc/hosts | head | while read line; do
  ((count++))
  echo $count $line
done
echo $count

和我的修复感谢这个帖子和process substitution

的帮助
count=0
while IFS= read -r line; do
  ((count++))
  echo "$count $line"
done < <(cat /etc/hosts | head)
echo "$count"

答案 5 :(得分:2)

USCOUNTER=$(grep -c "^US " "$FILE")

答案 6 :(得分:0)

增量变量可以这样做:

  _my_counter=$[$_my_counter + 1]

使用grep

计算列中模式的出现次数
 grep -cE "^([^ ]* ){2}US"

-c计数

([^ ]* )检测上校

{2}结肠号

US你的模式

答案 7 :(得分:0)

使用以下1行命令在linux中使用短语特异性更改许多文件名:

find -type f -name '*.jpg' | rename 's/holiday/honeymoon/'

对于扩展名为&#34; .jpg&#34;的所有文件,如果它们包含字符串&#34;假日&#34;,请将其替换为#34;蜜月&#34;。例如,此命令将重命名文件&#34; ourholiday001.jpg&#34; to&#34; ourhoneymoon001.jpg&#34;。

此示例还说明了如何使用find命令发送扩展名为.jpg(-name&#39; *。jpg&#39;)的文件列表(-type f),以通过管道重命名(| )。然后重命名从标准输入中读取其文件列表。