条件式の「set -e」での「eval」の動作


9

コマンドを検討する

eval false || echo ok
echo also ok

通常、我々はこれを実行するために期待するfalseユーティリティをして、終了ステータスがゼロであることから、その後、実行するecho okecho also ok

すべてのPOSIXのような私が使用してシェルでは(ksh93zshbashdash、OpenBSDのksh、とはyash)、これは何が起こるかですが、私たちは有効にした場合、物事は面白くset -e

set -eが有効な場合、OpenBSD shkshシェル(どちらもから派生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 okstring=false


eval falseゼロ以外のステータスを生成するのでset -e、その時点でスクリプトを終了する予定です。以下の場合! set -eのように適用されない!文で明示的に終了ステータスをチェックします。
fcbsd

@fcbsd eval falseAND-ORリストまたは条件ステートメントの一部であっても、スクリプトを終了することを期待しますか?私はしません。
クサラナンダ

これがset -e正しい動作であるかどうかが設定されているかどうかはわかりません...条件付きステートメントで終了しないことが理にかなっていることに同意します。
fcbsd

CentOS 7でshを使ってさらに演奏した-これは、OpenBSDのksh / shを使用set -eする場合の動作であり、 `()`が答えです。
fcbsd

回答:


4

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

||コマンドラインにaがあることは、その左側の戻りコード1によって引き起こされるシェルの終了を回避する必要があります。

特別な組み込みのエラーは、POSIXに準拠した非対話型シェルの終了を引き起こしますが、常にそうであるとは限りません。continueループから抜け出そうとするとエラーになりcontinue、組み込みです。しかし、ほとんどのシェルは終了しません:

continue 3

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

そのため、exit on falseset -e、コマンドの組み込み特性(evalこの場合)ではなく条件によって生成されます。

set -e終了する正確な条件は、POSIXではかなりあいまいです。


これは私がOpenBSDメーリングリストから得た返答を反映していますが、もっと多くの言葉で感謝します!適切なバグレポートを整理し、何も起こらない場合は、自分でソースコードを確認します。
クサラナンダ

4

[これが本当の答えではない場合は申し訳ありませんが、私がそれに答えたら更新します]

私はソースコードを見て、私の結論は次のとおりです。

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

2)OpenBSDのksh(mksh)のポータブルフォークからの「修正」は非常に貧弱で、実際に修正せずに事態を悪化させるだけです。

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

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、など

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.