条件表达式中“set -e”下“eval”的行为

Kus*_*nda 12 openbsd posix eval

考虑命令

eval false || echo ok
echo also ok
Run Code Online (Sandbox Code Playgroud)

通常,我们希望它执行false实用程序,并且由于退出状态非零,然后执行echo okecho also ok

在我使用的所有类似 POSIX 的 shell(ksh93zshbashdash、 OpenBSDkshyash)中,都会发生这种情况,但是如果我们启用set -e.

如果set -e有效,OpenBSDshkshshell(均源自pdksh)将在执行eval. 没有其他外壳能做到这一点。

POSIX 表示特殊内置实用程序(例如eval)中的错误应导致非交互式 shell 终止。我不完全确定执行是否false构成“错误”(如果是,则与set -e活动无关)。

解决此问题的方法似乎是将其放入eval子外壳中,

( eval false ) || echo ok
echo also ok
Run Code Online (Sandbox Code Playgroud)

问题是我是否需要在 POSIX-ly 正确的 shell 脚本中这样做,或者它是否是 OpenBSD 的 shell 中的错误?另外,上面链接的 POSIX 文本中的“错误”是什么意思?


额外的信息:OpenBSD shell 将 在命令中执行echo ok有和没有set -e

eval ! true || echo ok
Run Code Online (Sandbox Code Playgroud)

我的原始代码看起来像

set -e
if eval "$string"; then
    echo ok
else
    echo not ok
fi
Run Code Online (Sandbox Code Playgroud)

不会not okstring=false使用 OpenBSD shell 时输出(它会终止),而且我不确定这是由于设计、错误或误解或其他原因造成的。

ImH*_*ere 5

没有其他 shell 需要这样的解决方法,这强烈表明它是 OpenBSD ksh 中的一个错误。事实上,ksh93 并没有出现这样的问题。

||命令行中有 a必须避免左侧返回码为 1 导致的 shell 退出。

根据POSIX特殊内置程序的错误将导致非交互式 shell 的退出,但这并不总是正确的。试图跳出循环是一个错误,并且是一个内置的。但大多数 shell 不会退出:continuecontinue

continue 3
Run Code Online (Sandbox Code Playgroud)

发出明确错误但不退出的内置函数。

因此,退出 onfalse是由set -e条件生成的,而不是由命令的内置特性生成的(eval在这种情况下)。

set -e在 POSIX 中,退出的确切条件相当模糊。