條件表達式中「set -e」下「eval」的行為

條件表達式中「set -e」下「eval」的行為

考慮命令

eval false || echo ok
echo also ok

通常,我們期望它執行該false實用程序,並且由於退出狀態非零,因此執行echo okecho also ok

在我使用的所有類似 POSIX 的 shell(ksh93zshbashdashOpenBSDkshyash)中,都會發生這種情況,但是如果我們啟用 ,事情就會變得有趣set -e

如果set -e有效,OpenBSDshkshshell(均源自pdksh)將在執行eval.沒有其他外殼可以做到這一點。

POSIX 說特殊內建實用程式(例如eval)中的錯誤應導致非互動式 shell 終止。我不完全確定執行是否構成“錯誤”(如果是,則與活動狀態false無關)。set -e

解決這個問題的方法似乎是將其放入eval子外殼中,

( eval false ) || echo ok
echo also ok

問題是我是否需要在 POSIX 正確的 shell 腳本中執行此操作,或者這是否是 OpenBSD shell 中的錯誤?另外,上面連結的 POSIX 文字中的「錯誤」是什麼意思?


額外的資訊:OpenBSD shell 將執行 命令中的echo okwith 和 withoutset -e

eval ! true || echo ok

我原來的程式碼看起來像

set -e
if eval "$string"; then
    echo ok
else
    echo not ok
fi

這將不是not ok使用OpenBSD shell 的輸出string=false(它會終止),我不確定這是設計使然、錯誤還是誤解,還是其他原因。

答案1

沒有其他 shell 需要這樣的解決方法,這有力地表明這是 OpenBSD ksh 中的一個錯誤。事實上,ksh93 並沒有出現這樣的問題。

命令列中有一個||必須避免其左側返回碼為1而導致shell退出。

的錯誤是特別的內建將導致非互動式 shell 退出根據 POSIX但情況並非總是如此。嘗試continue跳出循環是一個錯誤,並且continue是內建的。但大多數 shell 不會在以下情況下退出:

continue 3

發出明顯錯誤但不退出的內建函數。

因此,退出false是由set -e條件產生的,而不是由命令的內建特徵產生的(eval在本例中)。

在 POSIX 中,退出的確切條件set -e相當模糊。

答案2

[抱歉,如果這不是真正的答案,我會在空閒時更新]

我查看了原始程式碼,我的結論是:

1)這是一個錯誤/限制,背後沒有任何哲學意義。

2) OpenBSD 的 ksh ( ) 的可移植分支對此的「修復」mksh非常糟糕,只會讓事情變得更糟,而沒有真正解決問題:

新錯誤,與所有其他 shell 不同:

mksh -ec 'eval "false; echo yup"'
yup

bash -ec 'eval "false; echo yup"'
(nothing)

仍然沒有真正解決:

mksh -ec 'eval "set -e; false" || echo yup'
(nothing)

bash -ec 'eval "set -e; false" || echo yup'
yup

您可以將bash上面替換為dash, zsh, yash,ksh93等。

相關內容