コマンドを検討する
eval false || echo ok
echo also ok
通常、これはfalse
ユーティリティを実行し、終了ステータスがゼロ以外であるため、echo ok
およびecho also ok
を実行することを期待します。
私が使用するすべてのPOSIX風のシェルで(ksh93
、zsh
、bash
、dash
、OpenBSD ksh
、およびyash
)、これは何が起こるかですが、set -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がnot ok
をstring=false
で出力します(終了します)。意図的に、誤って、または誤解して、あるいは何か他のものでした。
他のシェルがそのような回避策を必要としないことは、それがOpenBSD kshのバグであることを強く示しています。実際、ksh93はそのような問題を示していません。
コマンドラインに||
があることは、その左側の戻りコード1によって引き起こされるシェル出口を回避する必要があることを意味します。
specialビルトインのエラーにより、非対話型シェル POSIXに従って が終了しますが、常にそうであるとは限りません。ループからcontinue
を実行しようとするとエラーが発生し、continue
は組み込みです。しかし、ほとんどのシェルは終了しません:
continue 3
明確なエラーを発生するが終了しない組み込み関数。
したがって、false
の出口は、コマンドの組み込み特性(この場合はeval
)ではなく、set -e
条件によって生成されます。
set -e
が終了する正確な条件は、POSIXではかなりあいまいです。
[これが本当の答えではない場合は申し訳ありませんが、問題が出てきたら更新します]
私はソースコードを見て、私の結論は次のとおりです。
1)それはバグ/制限であり、その背後に哲学的なものは何もありません。
2)OpenBSDのksh(mksh
)のポータブルフォークからの「修正」はvery貧弱で、実際に修正せずに事態を悪化させるだけです。
他のすべてのシェルとは異なる新しいバグ:
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
などに置き換えることができます。