简体   繁体   English

由于bash的范围而导致的可变损失价值

[英]Variable losing value due to scope in bash

My bash version is GNU bash, version 4.3.42(1)-release (x86_64-pc-linux-gnu) . 我的bash版本是GNU bash,版本4.3.42(1)-发行版(x86_64-pc-linux-gnu) This is a simplified version of my script: 这是我的脚本的简化版本:

#!/bin/bash
touch a.ecl
touch b.ecl

function_syntaxCheckFileName()
{
  return 1 # 1 syntax error
}

tmpTotalErrors=0
result=0
echo "DEBUG Starting loop"
find . -name '*.ecl' -print0 | while read -d $'\0' file
do 
  echo " DEBUG - FILE=$file"
  echo "  DEBUG0 tmpTotalErrors=$tmpTotalErrors --- result=$result"
  function_syntaxCheckFileName "$file" 
  result=$?
  echo "  DEBUG1 tmpTotalErrors=$tmpTotalErrors --- result=$result"
  tmpTotalErrors=$((tmpTotalErrors + result)) 
  echo "  DEBUG2 tmpTotalErrors=$tmpTotalErrors --- result=$result"
done

echo "DEBUG3 tmpTotalErrors=$tmpTotalErrors"

It is designed to be run in path with spaces so I use this iteration 它被设计为在带有空格的路径中运行,因此我使用此迭代

find . 找 。 -name '*.ecl' -print0 | 名称'* .ecl'-print0 | while read -d $'\\0' file 同时读取-d $'\\ 0'文件

The output is this: 输出是这样的:

DEBUG Starting loop
 DEBUG - FILE=./a.ecl
  DEBUG0 tmpTotalErrors=0 --- result=0
  DEBUG1 tmpTotalErrors=0 --- result=1
  DEBUG2 tmpTotalErrors=1 --- result=1
 DEBUG - FILE=./b.ecl
  DEBUG0 tmpTotalErrors=1 --- result=1
  DEBUG1 tmpTotalErrors=1 --- result=1
  DEBUG2 tmpTotalErrors=2 --- result=1
DEBUG3 tmpTotalErrors=0

My problem is that tmpTotalErrors lose its value. 我的问题是tmpTotalErrors失去了它的价值。 It was supposed to be 2 and it is 0. 应该是2,是0。

So my questions are: 所以我的问题是:

  1. How can I my script work? 我的脚本如何工作?
  2. Why is failing? 为什么会失败?

Rewrite the loop to avoid subshel by using set +m; 通过使用set + m来重写循环,以避免子缓冲 shopt -s lastpipe shopt -s lastpipe

 #!/bin/bash
set +m 
shopt -s lastpipe
touch a.ecl
touch b.ecl

function_syntaxCheckFileName()
{
  return 1 # 1 syntax error
}

tmpTotalErrors=0
result=0
echo "DEBUG Starting loop"

find . -name '*.ecl' -print0 | while read -d $'\0' file
do 
  echo " DEBUG - FILE=$file"
  echo "  DEBUG0 tmpTotalErrors=$tmpTotalErrors --- result=$result"
  function_syntaxCheckFileName "$file" 
  result=$?
  echo "  DEBUG1 tmpTotalErrors=$tmpTotalErrors --- result=$result"
  tmpTotalErrors=$((tmpTotalErrors + result)) 
  echo "  DEBUG2 tmpTotalErrors=$tmpTotalErrors --- result=$result"
done
echo "DEBUG3 tmpTotalErrors=$tmpTotalErrors"

It's failing because changes in subshell don't reflect in the parent shell. 之所以失败,是因为外壳中的更改未反映在父外壳中。

Also see this Bash FAQ entry: I set variables in a loop that's in a pipeline. 另请参阅此Bash FAQ条目: 我在管道的循环中设置变量。 Why do they disappear after the loop terminates? 为什么它们在循环终止后消失了? Or, why can't I pipe data to read? 或者,为什么我不能通过管道读取数据? which discusses a number of alternative solutions. 其中讨论了许多替代解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM