Bash がコマンド置換に errexit オプションを渡さないのはなぜですか?

Bash がコマンド置換に errexit オプションを渡さないのはなぜですか?

シェルオプションの設定set組み込みはサブシェル(少なくともerrexit)に継承されます。これは次のように証明できます。

set -o errexit

function foo() {
    echo "foo:$BASHPID"
    false
    echo 'after' 
}

echo "main:$BASHPID"
( foo )

しかし、オプションは継承されていないようですコマンド置換、Bash のドキュメントによれば、これもサブシェルであるはずです。証明:

set -o errexit

function foo() {
    echo "foo:$BASHPID"
    false
    echo 'after' 
}

echo "main:$BASHPID"
output=$(foo)
echo "output: $output"

期待される出力:

main:123
output: foo:124

実際の出力:

main:123
output: foo:124
after

それは予想通りのことでしょうか、それともバグでしょうか?

答え1

はい、POSIX モードではない場合 ( として実行している場合などsh)、bash はerrexitデフォルトでコマンド置換の内部をリセットすることが予想されます。

errexitbash 4.4 以降でコマンド置換の内部を保持したい場合は、次を使用します。

inherit_errexit

errexit設定されている場合、コマンド置換はサブシェル環境でオプションの値を設定解除するのではなく、オプションの値を継承します。このオプションは、POSIX モードが有効な場合に有効になります。

(からBash マニュアルドキュメントからの別の部分より明確にしました:

POSIX モードを有効にするとオプションが設定される効果があり、コマンド置換を実行するために生成されたサブシェルは親シェルからオプションinherit_errexitの値を継承します。-eオプションが有効になっていない場合inherit_errexit、Bash は-eそのようなサブシェル内のオプションをクリアします。

検証します:

$ bash -o errexit -c 'echo "$(echo "$SHELLOPTS")"'
braceexpand:hashall:interactive-comments
$ bash -o errexit -O inherit_errexit -c 'echo "$(echo "$SHELLOPTS")"'
braceexpand:errexit:hashall:interactive-comments

bash 4.2 以前では、errexit前者では表示されていましたが、実際には無効になっています。

$ bash-4.2 -o errexit c 'echo "$(false; echo "$SHELLOPTS")"'
braceexpand:errexit:hashall:interactive-comments
$ bash-4.2 -o posix -o errexit -c 'echo "<$(false; echo "$SHELLOPTS")> $?"'
<> 1

関連情報