2015-01-06 84 views
12

我在我的腳本中使用了一個簡單的bash序言這樣的功能:使用set -e /套+ E在bash與

#!/bin/bash 
set -e 

與模塊結合/使用此功能現在已經咬傷了我。

所以,說我有一個像

foo() { 
    #edit: some error happens that make me want to exit the function and signal that to the caller 
    return 2 
} 

某處功能理想情況下,我想能夠使用多個小文件,包括其他文件中的函數,然後調用這些功能,如

set +e 
foo 
rc=$? 
set -e 

。這適用於兩層例程。但是如果foo也調用這樣的子例程,返回前的最後一個設置將是set -e,這將使腳本退出 - 我不能在調用函數中重寫此函數。所以,我不得不這樣做是

foo() { 
    #calling bar() in a shielded way like above 
    #..  

    set +e 
    return 2 
} 

我覺得這非常違反直覺的(也是不是我想要的 - 如果在某些情況下我想使用的功能,不帶屏蔽免遭失敗,而在其他情況下什麼我想處理清理?)處理這個問題的最佳方法是什麼?順便說一句。我在OSX上這樣做,我沒有測試這種行爲在Linux上是不同的。

+0

等待,你能擴大嗎?我在呼叫者中添加了這個嗎?結腸是做什麼的? –

+0

你能否擴展我如何濫用回報?我怎麼打算在函數內發出錯誤信號呢? (對不起,如果我不夠清楚 - 'return 2'只能在錯誤情況下完成。 –

+1

你不是,但我以爲你是我的壞人,對不起。 – Carpetsmoker

回答

13

Shell函數並沒有真正的「返回值」,只是退出代碼。

你可以添加&& :給調用者,這使得「測試」的命令,將不會退出它:

foo() { 
    echo 'x' 
    return 42 
} 

out=$(foo && :) 
echo $out 

:是「空指令」(即它不這樣做。任何東西)。在這種情況下,它甚至不會被執行,因爲只有當foo返回0(它沒有)時它纔會運行。

此輸出:

x 

這可以說是醜了一點,但還是那句話,所有shell腳本可以說是有點難看;-)

從FreeBSD的,這也解釋了這個優於報價sh(1) bash的手冊頁:

-e errexit 
     Exit immediately if any untested command fails in non-interactive 
     mode. The exit status of a command is considered to be explicitly 
     tested if the command is part of the list used to control an if, 
     elif, while, or until; if the command is the left hand operand of 
     an 「&&」 or 「||」 operator; or if the command is a pipeline preceded 
     by the ! operator. If a shell function is executed and its exit 
     status is explicitly tested, all commands of the function are con‐ 
     sidered to be tested as well. 
+0

(該死的,評論中沒有新行;) )。謝啦。我現在明白了。所以從現在開始,如果我想執行一個'測試'的方式,我會做 set + e foo &&: rc = $? set -e –

+1

@MichelMüller你不需要用'set'做任何事情;你只需使用'set -e'一次在你的腳本中啓用它,然後使用'&&:'來「繞過它」。 – Carpetsmoker

+0

對,有道理。謝謝。 –