考虑命令
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
等。