web-dev-qa-db-ja.com

関数で実行されていないBashのRETURNトラップ

私は再びBashの罠に手を出しています。 RETURNトラップが関数に対して起動しないことに気づきました。

$ trap 'echo ok' RETURN
$ f () { echo ko; }
$ f
ko
$ . x
ok
$ cat x
$ 

ご覧のように、空のファイルxを調達することで期待どおりに動作します。

Bashのmanはそうです。

SigspecがRETURNの場合、コマンドargは、Shell関数またはスクリプトがで実行されるたびに実行されます。または、ソースのビルトインが実行を終了します。

それで私は何が欠けていますか?

GNU bash、バージョン4.4.12(1)-release(x86_64-pc-linux-gnu))があります。

6
user147505

私はこれを理解しているので、私の質問のドキュメントスニペットには例外があります。スニペットは:

SigspecがRETURNの場合、コマンドargは、Shell関数またはスクリプトがで実行されるたびに実行されます。または、ソースのビルトインが実行を終了します。

例外は次のとおりです。

シェル実行環境の他のすべての側面は、関数とその呼び出し元で同じですが、次の例外があります:DEBUGトラップとRETURNトラップ(トラップの説明を参照)シェルのビルトインビルトインコマンド(下のビルトインコマンド)は、関数にtrace属性が指定されていないか(下のビルトインの宣言の説明を参照)、または-o functraceシェルオプションがset builtin(この場合、すべての関数がDEBUGトラップとRETURNトラップを継承します)、および-o errtraceシェルオプションが有効になっていない限り、ERRトラップは継承されません。

functraceについては、typeset-tでオンにすることができます。

-tそれぞれの名前にトレース属性を与えます。トレースされた関数は、呼び出し元のシェルからDEBUGおよびRETURNトラップを継承します。 trace属性は、変数に対して特別な意味を持ちません。

また、set -o functraceがトリックを行います。

これがイラストです。

$ trap 'echo ko' RETURN
$ f () { echo ok; }
$ cat y
f
$ . y
ok
ko
$ set -o functrace
$ . y
ok
ko
ko

declareについては、再び-tオプションです。

-tそれぞれの名前にトレース属性を与えます。トレースされた関数は、呼び出し元のシェルからDEBUGおよびRETURNトラップを継承します。 trace属性は、変数に対して特別な意味を持ちません。

また、extdebugikkachuの回答 のように関数トレースを有効にします。

5
user147505

Bash 4.4では、extdebugが有効になっている場合にのみ機能するように見えますが、ドキュメントに記載されていることはわかりません。

$ cat ret.sh 
trap "echo ret" RETURN
foo() { echo "$1"; }
foo "without extdebug"
shopt -s extdebug
foo "with extdebug"

$ bash ret.sh
without extdebug
with extdebug
ret

$ bash --version |head -1
GNU bash, version 4.4.12(1)-release (x86_64-pc-linux-gnu)

Bash 4.3では、関数に対してまったく機能しないようです。

1
ilkkachu