シェルオプションの設定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
デフォルトでコマンド置換の内部をリセットすることが予想されます。
errexit
bash 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