次のスクリプトを使用しています。
#!/bin/bash -Eu
trap 'echo Hi' ERR
exit_failure() {
echo "Hello, World!"
return 1
}
sub_failure() {
res=$(exit_failure)
}
sub_failure
結果は次のとおりです。
Hi
Hi
しかし、sub_failure()
次のように変更した場合:
sub_failure() {
local res=$(exit_failure)
}
もはや出力が出ませERR
んか?信号が隠されているのはなぜですか?ERR
ローカル変数を使用するにはどのようにキャプチャする必要がありますか?できることはわかりますが、local res; res=$(exit_failure)
なぜそれらを分離する必要がありますか?
ベストアンサー1
これは間違いではありません。これは実際に定義された動作です。
あなたがそれを使用するとbash -Eux
何が起こるのかを見ることができます。 (-Eu
あなたのshebangで+ -x
)
+ trap 'echo Hi' ERR
+ sub_failure
++ exit_failure
++ echo 'Hello, World!'
++ return 1
+++ echo Hi
+ res='Hello, World!
Hi'
++ echo Hi
Hi
++ echo Hi
Hi
コマンド置換を実行すると、スイッチtrap
によって-E
継承されます。したがって、関数return 1
によってトリガされた継承トラップの「Hi」は。 (実行バリアントを使用する場合も同様です)exit_failure()
ret
local
また、res=...
式は1
(エラー)を返し、トラップ(sub_failure()
関数内)をトリガーします。
res=...
関数のreturnと結果は1
関数の最後のコマンドの結果であるため、結果もエラーであり、sub_failure()
メインシェルで実行1
後にトラップが再トリガされます。sub_failure
したがって、2つの「Hi」が表示されます。 forres=....
とforsub_failure
と隠された「Hi」がに保存されます$res
。
local
それではバリエーションについて話しましょう。
+ trap 'echo Hi' ERR
+ sub_failure
++ exit_failure
++ echo 'Hello, World!'
++ return 1
+++ echo Hi
+ local 'res=Hello, World!
Hi'
定義によると、関数内で使用されるときはlocal
常に返されます。評価結果も返されるため、隠された「Hi」を保存しながら(成功)と評価することになります0
。したがって、今回は「隠された」失敗1つと成功2つを得ることになります。local res=...
0
$res
res=..
0
sub_failure
0
このスレッドは古いですが、役に立つことを願っています。 ;)
local res=...
また、私たちが分割しなければならない理由も明らかです。
local res
res=....
最初のバリエーションの動作を復元します。 ;)