2

我想制作一个构建链脚本,如果编译过程中出现错误,我不希望它执行到最后。

这是我第一次在 bash 中编写更“详细”的脚本,但它不起作用:

  1. 它没有回显错误,尽管我在其中有带有错误一词的行
  2. 无论 testError 的值是多少,脚本都会挂在行中

这是代码:

testError=false

output=$(scons)
while read -r line; do
    if [[ $line == .*[eE]rror.* ]] ; then echo 'ERROR' ; $testError = true ; fi #$testError = true fi
done

echo $testError
if  $testError  ; then exit ; fi;

... other commands

编辑:按照所有海报的答案和Bash 在循环内设置全局变量并保留其值 - 或处理假人的替代以及如何在 bash 脚本中使用正则表达式?,这是代码的最终版本。有用:

testError=false

shopt -s lastpipe
scons | while read -r line; do
  if [[ $line =~ .*[eE]rror.* ]] ; then
    echo -e 'ERROR' 
    testError=true 
  fi 
  echo -e '.'
done

if  $testError  ; then
    set -e 
fi
4

5 回答 5

2

testError您在管道诱导的子外壳中设置 的值。当该子外壳退出时(在管道的末端),您所做的任何更改都会消失。试试这个:

while read -r line; do
   if [[ $line == .*[eE]rror.* ]] ; then
     echo -e 'ERROR' 
     testError=true 
   fi #$testError = true fi
done < <( scons )

或者,如果您不想或不能使用进程替换,请使用临时文件

scons > tmp
while read -r line; do
  if [[ $line == .*[eE]rror.* ]] ; then
    echo -e 'ERROR' 
    testError=true 
  fi #$testError = true fi
done < tmp

这消除了管道,因此更改testError在 while 循环之后持续存在。

而且,如果您的 bash 版本足够新(4.2 或更高版本),则有一个选项允许管道末尾的 while 循环在当前 shell 中执行,而不是在子 shell 中执行。

shopt -s lastpipe
scons | while read -r line; do
  if [[ $line == .*[eE]rror.* ]] ; then
    echo -e 'ERROR' 
    testError=true 
  fi #$testError = true fi
done
于 2013-02-14T00:00:54.250 回答
1

你应该试试

set -e

如果命令以非零状态退出,这将停止脚本继续

或更好

error_case() { # do something special; }
trap 'echo >&2 "an error occurs"; error_case' ERR

error_case每次命令以非零状态退出时运行此函数

http://mywiki.wooledge.org/BashFAQ/105

于 2013-02-13T23:47:03.077 回答
1

您是否正在尝试解析 scons 的输出?

这:

output=$(scons)
while read -r line; do
    if [[ $line == .*[eE]rror.* ]] ; then 
        echo 'ERROR' 
        testError=true
    fi
done

不这样做。也许你想要:

scons | while read -r line; do ... ; done
于 2013-02-13T23:48:11.770 回答
1

另一个错误是作业中有空格。并跳过$

$testError = true

应该

testError=true

编辑

testerror 在子shell 中更改。尝试

testerror=$(
    scons | while read -r line; do
        if [[ $line == .*[eE]rror.* ]] ; then
            echo true 
        fi #$testError = true fi
    done
)
于 2013-02-13T23:53:11.843 回答
0

我回答也是因为其他答案没有注意到:应该以这种方式使用正则表达式,使用=~而不是==

if [[ $line =~ .*[eE]rror.* ]] ; then
...

cf如何在 bash 脚本中使用正则表达式?

于 2013-02-14T00:48:10.893 回答