条件式における「set -e」での「eval」の動作

条件式における「set -e」での「eval」の動作

コマンドを検討する

eval false || echo ok
echo also ok

false通常、これによりユーティリティが実行され、終了ステータスがゼロでないため、およびが実行されるecho okと考えられますecho also ok

私が使用しているすべての POSIX ライクなシェル ( ksh93、、、OpenBSD 、および) では、これが起こりますが、 を有効にすると興味深いことが起こりzshます。bashdashkshyashset -e

set -eが有効な場合、OpenBSD のshおよびkshシェル (両方とも から派生pdksh) は を実行するときにスクリプトを終了しますeval。他のシェルではこれを行いません。

POSIXによれば特別な組み込みユーティリティ (などeval) でエラーが発生すると、非対話型シェルが終了するはずです。 を実行することがfalse「エラー」を構成するかどうかはよくわかりません (そうであれば、アクティブであることとは無関係ですset -e)。

これを回避するには、evalサブシェルに

( eval false ) || echo ok
echo also ok

問題は、これを POSIX 準拠のシェル スクリプトで行う必要があるのか​​、それとも OpenBSD のシェルのバグなのかということです。また、上記にリンクされている POSIX テキストの「エラー」とはどういう意味ですか。


追加情報: OpenBSDシェルは コマンドのecho okありとなしの両方を実行します。set -e

eval ! true || echo ok

私の元のコードは次のようになりました

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

それはないOpenBSD シェルを使用するnot okと出力が終了してしまいますが、それが設計によるものなのか、間違いや誤解によるものなのか、あるいは他の何かによるものなのかはわかりませんでした。string=false

答え1

他のシェルではこのような回避策が必要ないということは、それが OpenBSD ksh のバグであることを強く示唆しています。実際、ksh93 ではこのような問題は発生しません。

コマンドラインにがある場合、||その左側の戻りコード 1 によって発生するシェルの終了を回避する必要があります。

エラー特別組み込みは非対話型シェルを終了させるPOSIXによるとしかし、それは常に正しいわけではありません。continueループから抜けようとするとエラーになり、これはcontinue組み込みのエラーです。しかし、ほとんどのシェルは次のような場合には終了しません。

continue 3

明確なエラーを発行するが終了しない組み込み関数。

したがって、 exit on は、コマンドの組み込み特性 (この場合は)ではなくfalse条件によって生成されます。set -eeval

POSIX では、終了する正確な条件はset -eかなり曖昧です。

答え2

[これが本当の答えでなければ申し訳ありません。時間ができたら更新します]

ソースコードを見て、次のような結論に達しました。

1) これはバグ/制限であり、その背後に哲学的な根拠は何もありません。

mksh2) OpenBSDのksh ( )のポータブルフォークからの「修正」は、とても残念なことに、事態を悪化させるだけで、実際には解決しません。

他のすべてのシェルとは異なる新しいバグ:

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、、、などに置き換えることができますzshyashksh93

関連情報