簡體   English   中英

使用set -e時,bash單行條件失敗

[英]bash one-line conditional fails when using set -e

我開始在bash腳本中使用set -e,發現條件表達式的簡短形式破壞了腳本的執行。

例如,以下行應檢查$ var是否為空:

[ -z "$var" ] && die "result is empty"

但是當$ var具有非零長度時,會導致腳本無提示退出。

我在很多地方都使用了這種形式的條件表達式...

我應該怎么做才能使其正常運行? 用“ if”構造重寫所有內容(這很丑)? 還是放棄“ set -e”?

編輯:每個人都在要求代碼。 這是完整的[非]工作示例:

#!/bin/bash
set -e

function check_me()
{
    ws="smth"
    [ -z "$ws" ] && echo " fail" && exit 1
}

echo "checking wrong thing"
check_me
echo "check finished"

我希望它在函數調用之前和之后都打印回顯。 但是它在check_me函數中無提示地失敗了。 輸出為:

checking wrong thing

采用

[ -n "$var" ] || die "result is empty"

這樣,如果$var為非空值,則整個語句的返回值為true,因此不會觸發ERR陷阱。

您應該編寫腳本,以使任何命令都不會以非零狀態退出。

在您的命令中[ -z "$var" ]可以為true,在這種情況下,您調用die ,或者為false,在這種情況下, -e就是這樣。

如您所說,可以使用if編寫它,也可以使用如下代碼:

[ -z "$var" ] && die "result is empty" || true

我會建議if

恐怕您將不得不重寫所有內容,以免發生錯誤的陳述。

set -e的定義很明確:

-e如果簡單命令(請參見上面的SHELL GRAMMAR)以非零狀態退出,則立即退出。 如果失敗的命令緊隨一段時間或直到關鍵字,if語句中測試的一部分,&&或||的一部分之后的命令列表的一部分,則外殼程序不會退出。 列表,或者命令的返回值通過!反轉。 退出外殼之前,將執行ERR上的陷阱(如果已設置)。

您正在使用Bash的“優化”系統:因為錯誤的語句將導致AND( && )語句永遠不為真,因此bash知道不必執行該行的第二部分。 但是,這是對系統的巧妙“濫用”,不是預期的行為,因此與set -e不兼容。 您將必須重寫所有內容,因此if使用s則使用正確的內容。

bash幫助尚不清楚的是,只有&&||最后一條語句 鏈會導致在set -e下退出。 如果bar返回false,則foo && bar將退出,但如果foo返回false,則不會退出。

因此,您的腳本應該可以工作...但是不能。 為什么?

這不是因為-z測試失敗。 這是因為失敗使函數 返回非零狀態

#!/bin/bash
set -e

function check_me()
{
    ws="smth"
    [ -z "$ws" ] && echo " fail" && exit 1
    # The line above fails, setting $? to 1
    # The function now returns, returning 1!
}

echo "checking wrong thing"
check_me   # function returns 1, causing exit here
echo "check finished"

因此,有多種方法可以解決此問題。 您可以在函數內部的條件check_me或調用check_me的行中添加||true 但是,正如其他人指出的那樣,使用||true有其自身的問題。

在此特定場景中, check_me的所需后置條件是“此內容有效或腳本已退出”,直接要做的就是這樣寫它,即[[ -n "$ws" ]] || die "whatever" [[ -n "$ws" ]] || die "whatever"

但是,通常只要不將條件作為函數中的最后一項,使用&&條件實際上通常可以與set -e配合使用。 您需要添加一個明確的truereturn 0 ,甚至:作為一個語句之后這樣的條件,除非你打算的功能,當條件不滿足返回false。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM