考慮命令
eval false || echo ok
echo also ok
通常,我們期望它執行該false
實用程序,並且由於退出狀態非零,因此執行echo ok
和echo also ok
。
在我使用的所有類似 POSIX 的 shell(ksh93
、zsh
、bash
、dash
OpenBSDksh
和yash
)中,都會發生這種情況,但是如果我們啟用 ,事情就會變得有趣set -e
。
如果set -e
有效,OpenBSDsh
和ksh
shell(均源自pdksh
)將在執行eval
.沒有其他外殼可以做到這一點。
POSIX 說特殊內建實用程式(例如eval
)中的錯誤應導致非互動式 shell 終止。我不完全確定執行是否構成“錯誤”(如果是,則與活動狀態false
無關)。set -e
解決這個問題的方法似乎是將其放入eval
子外殼中,
( eval false ) || echo ok
echo also ok
問題是我是否需要在 POSIX 正確的 shell 腳本中執行此操作,或者這是否是 OpenBSD shell 中的錯誤?另外,上面連結的 POSIX 文字中的「錯誤」是什麼意思?
額外的資訊:OpenBSD shell 將執行 命令中的echo ok
with 和 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
等。