[英]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
配合使用。 您需要添加一個明確的true
或return 0
,甚至:
作為一個語句之后這樣的條件,除非你打算的功能,當條件不滿足返回false。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.