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


10

考虑命令

eval false || echo ok
echo also ok

通常,我们希望它能够执行该false实用程序,并且由于退出状态为非零,因此可以执行echo okecho also ok

在所有的类POSIX我用贝壳(ksh93zshbashdash,OpenBSD的ksh,和yash),这是发生了什么,但事情变得有趣的,如果我们能set -e

如果set -e有效,则执行时,OpenBSD shkshshell(均从派生pdksh)将终止脚本eval。没有其他外壳可以做到这一点。

POSIX说特殊的内置实用程序(例如eval)中的错误应导致非交互式外壳终止。我不确定执行是否false构成“错误”(如果确实如此,它将独立于set -e活动状态)。

解决此问题的方法似乎是将evalin 放在子shell中,

( eval false ) || echo ok
echo also ok

问题是,是否应该在POSIX正确的shell脚本中执行此操作,还是在OpenBSD的shell中出现错误?另外,上面链接到的POSIX文本中的“错误”是什么意思?


额外的信息:OpenBSD Shell将 在命令中echo ok使用和不使用两者set -e

eval ! true || echo ok

我的原始代码看起来像

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

这将输出not okstring=false使用OpenBSD的炮弹(它会终止),我不知道它是通过设计,错误或误会,还是其他什么东西。


eval false生成非零状态,因此我希望set -e在那时终止脚本。在! set -e不适用as !语句的情况下,显式检查退出状态。
fcbsd

@fcbsd eval false即使脚本是AND-OR列表或条件语句的一部分,您是否也希望终止该脚本?我不会
库萨兰达

我不确定是否set -e设置了正确的行为...我同意不终止于条件语句是有意义的。
fcbsd

在CentOS 7上使用sh播放了更多内容-我想说这是使用OpenBSD的ksh / sh时的预期行为,set -e所以`()是答案。
fcbsd19年

Answers:


4

没有其他外壳程序需要这种解决方法,这充分表明它是OpenBSD ksh中的错误。实际上,ksh93不会显示此类问题。

||命令行中必须存在a ,必须避免因其左侧的返回码1导致shell退出。

特殊内置错误会导致退出非交互式外壳(根据POSIX),但这并不总是正确的。尝试continue跳出循环是一个错误,并且continue是内置的。但是大多数壳不会在以下位置退出:

continue 3

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

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

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


这与我从OpenBSD邮件列表中得到的回应相呼应,但请多多点谢意!我将整理出适当的错误报告,如果什么都没有发生,我将亲自查看源代码。
库萨兰达

4

[很抱歉,如果这不是一个真正的答案,我会在解决问题时更新它]

我看了一下源代码,得出的结论是:

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上面dashzshyashksh93,等。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.