此bash脚本出错

时间:2013-02-13 23:45:46

标签: bash

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

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

  1. 它不会回显ERROR,虽然我的行中包含单词error
  2. 无论testError的值如何,脚本都会挂起
  3. 这是代码:

    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
    

5 个答案:

答案 0 :(得分: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或更高版本),则有一个选项允许管道末尾的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

答案 1 :(得分: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

答案 2 :(得分: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

答案 3 :(得分:1)

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

$testError = true

应该是

testError=true

修改

在子shell中更改了testerror。尝试

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

答案 4 :(得分:0)

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

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

cf How do I use regular expressions in bash scripts?