2013-02-13 107 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 
)