関数内から関数名を判別する方法


163

次のようなBashスクリプトがある場合:

#!/bin/bash

f() {
  # echo function name, "f" in this case
}

これを行う方法はありますか?これは、次のようなヘルプメッセージで使用できます。

printf "Usage: %s: blah blah blah \n" $(basename $0) >&2; 

この場合のみ、私が欲しかったのは$0、スクリプトのファイル名です。


2
関連:FUNCNAME配列およびその他のBash変数を使用するBashロギングフレームワーク:github.com/codeforester/base/blob/master/lib/stdlib.sh。特に関数log_debug_enterを参照してくださいlog_debug_leave
codeforester

回答:


236

${FUNCNAME[0]}in bashを使用して関数名を取得できます。


79

バッシュリファレンス・マニュアル

FUNCNAME

現在実行呼び出しスタックにあるすべてのシェル関数の名前を含む配列変数。インデックス0の要素は、現在実行中のシェル関数の名前です。一番下の要素(最高のインデックスを持つ要素)は「メイン」です。この変数は、シェル関数の実行中にのみ存在します。FUNCNAMEへの割り当ては効果がなく、エラーステータスを返します。FUNCNAMEが設定されていない場合、その後リセットされても、特別なプロパティは失われます。

この変数は、BASH_LINENOおよびBASH_SOURCEで使用できます。FUNCNAMEの各要素には、BASH_LINENOおよびBASH_SOURCEに対応する要素があり、呼び出しスタックを記述します。たとえば、$ {FUNCNAME [$ i]}はファイル$ {BASH_SOURCE [$ i + 1]}から行番号$ {BASH_LINENO [$ i]}で呼び出されました。組み込みの呼び出し元は、この情報を使用して現在の呼び出しスタックを表示します。

インデックスなしでbash配列にアクセスすると、配列の最初の要素が返されるため$FUNCNAME、単純な場合に機能して、現在の関数の名前を提供しますが、呼び出しスタック内の他のすべての関数も含まれます。例えば:

# in a file "foobar"
function foo {
    echo foo
    echo "In function $FUNCNAME: FUNCNAME=${FUNCNAME[*]}" >&2
}

function foobar {
    echo "$(foo)bar"
    echo "In function $FUNCNAME: FUNCNAME=${FUNCNAME[*]}" >&2
}

foobar

出力されます:

$ bash foobar
In function foo: FUNCNAME=foo foobar main
foobar
In function foobar: FUNCNAME=foobar main

6
まだわかりません。[0]装飾されていない変数にアクセスすることで暗黙のifを追加するのはなぜですか?
トム・ヘイル

15
それは変数の実際の型を欺いて無知だからです?もちろん、それは常に必要なわけではありませんが、他の多くのバッシュイズムと同様に、怠惰な慣習です。曖昧であるよりも明確である方が良い。
bschlueter

36

${FUNCNAME[0]}現在の関数名を出力するために使用します


@bschlueterただし、Bashの配列のように処理せずに配列を参照すると、最初の値が出力されるだけです。したがって、受け入れられた答えはどのように間違っていますか?
Alexej Magura 2016年

4
確かに、それは便利ですが、メンテナンスとテストにはひどいものです。怠惰にしないでください、明示的にしてください。
bschlueter 2016年

1

もう一つの例:

# in a file "foobar"
foo() {
    echo "$FUNCNAME fuction begins"
}

foobar() {
    echo "$FUNCNAME fuction begins"
}

echo 'begin main'
foo
foobar
echo 'end main'

出力されます:

begin main
foo fuction begins
foobar fuction begins
end main

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