条件表达式中“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等。

相关内容