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

时间:2016-11-25 16:08:42

标签: bash

我的bash版本是 GNU bash,版本4.3.42(1)-release(x86_64-pc-linux-gnu)。这是我的脚本的简化版本:

#!/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"

它被设计为在路径中使用空格运行,因此我使用此迭代

  找到。 -name'* .ecl'-print0 |读取-d $'\ 0'文件

输出是:

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

我的问题是tmpTotalErrors失去了它的价值。它应该是2,它是0。

所以我的问题是:

  1. 我的剧本如何运作?
  2. 为什么会失败?

1 个答案:

答案 0 :(得分:3)

使用 set + m重写循环以避免使用subhel; 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"

它失败了,因为here中的更改不会反映在父shell中。

另请参阅此Bash常见问题解答条目:subshell,其中讨论了许多替代解决方案。