2013-02-13 111 views
2

我想制作一个构建链脚本,并且如果在编译过程中出现错误,我不希望它执行到结尾。此bash脚本中的错误

这是我第一次写的比较“论述了”在bash脚本,它只是不工作:

  1. 它没有回音ERROR虽然我有它
  2. 字错误线
  3. 无论是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 setting a global variable inside a loop and retaining its value -- Or process substituion for dummiesHow do I use regular expressions in bash scripts?, 这是代码的最终版本。 它的工作原理:

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 

回答

2

您在由管道引发的子shell中设置testError的值。当该子shell退出时(在管道的末尾),所做的任何更改都会消失。试试这个:

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或更高版本),则有一个选项允许在当前shell中执行管道末尾的while循环,而不是子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 
+0

如果有版本4.2.24,可能会这样做。 – 2013-02-14 00:19:46

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

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 
+0

是的,我想解析scons输出。 – 2013-02-13 23:49:09

+0

管道创建了一个子shell,其中'testError'的更改不再是全局的。 – chepner 2013-02-14 00:02:13

+0

@chepner我正在阅读这个问题,与你所指的相关:http://stackoverflow.com/questions/9012841/bash-setting-a-global-variable-inside-a-loop-and-retaining-它的值或程序 – 2013-02-14 00:13:23

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 
)