【问题标题】:Why does my Bash counter reset after while loop为什么我的 Bash 计数器在 while 循环后重置
【发布时间】:2011-02-15 16:14:50
【问题描述】:

我有一个 Bash 脚本,我想在其中计算循环文件时做了多少事情。计数似乎在循环中起作用,但在它之后变量似乎被重置。

nKeys=0
cat afile | while read -r line
do
  #...do stuff
  let nKeys=nKeys+1
  # this will print 1,2,..., etc as expected
  echo Done entry $nKeys
done
# PROBLEM: this always prints "... 0 keys"
echo Finished writing $destFile, $nKeys keys

上面的输出仅是以下几行:

完成条目 1 完成条目 2 写完/blah,0键

我想要的输出是:

完成条目 1 完成条目 2 写完/blah,2键

我不太确定为什么循环后 nKeys 为 0 :( 我认为这是基本的东西,但如果我能发现它,尽管查看了 http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-7.html 和其他资源,但该死的。

手指交叉的其他人可以看着它并说“好吧,你必须......”!

【问题讨论】:

  • mywiki.wooledge.org/BashFAQ/024">BASH FAQ 条目 #24:“我在循环中设置变量。为什么循环终止后它们会突然消失?或者,为什么我不能通过管道读取数据?”

标签: bash


【解决方案1】:

在刚刚发布的 Bash 4.2 中,您可以这样做来防止创建子 shell:

shopt -s lastpipe

此外,您可能会在 Ignacio 提供的链接中看到,您有一个 Useless Use of cat

while read -r line
do
    ...
done < afile

【讨论】:

  • 使用完该设置后如何撤消此“shopt -s lastpipe”?
  • @TimothySwan: help shopt 揭示了-u disable (unset) each OPTNAME,所以shopt -u lastpipe
  • 链接失效并重定向到广告页面。也许porkmail.org/era/unix/award.html
  • @DanielBöhmer:更新了链接。谢谢。
【解决方案2】:

正如接受的答案中提到的,这是因为管道产生了单独的子进程。为避免这种情况,command grouping 一直是我的最佳选择。也就是说,在子外壳中的管道之后执行所有操作。

nKeys=0
cat afile | 
{
  while read -r line
  do
    #...do stuff
    let nKeys=nKeys+1
    # this will print 1,2,..., etc as expected
    echo Done entry $nKeys
  done
  # PROBLEM: this always prints "... 0 keys"
  echo Finished writing $destFile, $nKeys keys
}

现在它将“正确”报告$nKeys 的值(即您希望的值)。

【讨论】:

  • 虽然这可行,但它是有限制的(变量仍然只存在于 group 命令中),并且有更好的选择:对于来自 file 的输入,使用 while ...; do ...; done &lt; afile,如在 Dennis Williamson 的回答中,对于来自 command 输出的输入,请使用 process substitution,例如while ...; do ...; done &lt; &lt;(cat -n afile).
【解决方案3】:

我在不使用管道或此处文档的情况下通过以下方式达到了预期的结果


#!/bin/sh
counter=0
string="apple orange mango egg indian"
str_len=${#string}
while [ $str_len -ne 0 ]
do
   c=${string:0:1}
   if  [[ "$c" = [aeiou] ]]
   then
       echo -n "vowel : "
       echo "- $c"
       counter=$(( $counter + 1 ))
   fi
   string=${string:1}
   str_len=${#string}
done
   printf "The number of vowels in the given string are : %s "$counter
   echo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-01
    • 2019-03-12
    • 2012-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多