So bestimmen Sie den Funktionsnamen innerhalb einer Funktion

163

Wenn ich ein Bash-Skript habe wie:

#!/bin/bash

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

Gibt es eine Möglichkeit, dies zu tun? Dies kann in Hilfemeldungen wie verwendet werden

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

Nur in diesem Fall wollte ich nicht $0, das ist der Dateiname des Skripts.

Yan
quelle
2
Verwandte Themen: Bash-Protokollierungsframework, das FUNCNAMEArray- und andere Bash-Variablen verwendet: github.com/codeforester/base/blob/master/lib/stdlib.sh . Siehe Funktionen log_debug_enterund log_debug_leaveinsbesondere.
Codeforester

Antworten:

236

Sie können ${FUNCNAME[0]}in verwenden bash, um den Funktionsnamen abzurufen.

TheBonsai
quelle
79

Aus dem Bash-Referenzhandbuch :

FUNCNAME

Eine Array-Variable, die die Namen aller Shell-Funktionen enthält, die sich derzeit im Ausführungsaufrufstapel befinden. Das Element mit dem Index 0 ist der Name einer aktuell ausgeführten Shell-Funktion. Das unterste Element (das mit dem höchsten Index) ist "main". Diese Variable existiert nur, wenn eine Shell-Funktion ausgeführt wird. Zuweisungen zu FUNCNAME haben keine Auswirkung und geben einen Fehlerstatus zurück. Wenn FUNCNAME nicht gesetzt ist, verliert es seine besonderen Eigenschaften, auch wenn es anschließend zurückgesetzt wird.

Diese Variable kann mit BASH_LINENO und BASH_SOURCE verwendet werden. Jedes Element von FUNCNAME verfügt über entsprechende Elemente in BASH_LINENO und BASH_SOURCE, um den Aufrufstapel zu beschreiben. Zum Beispiel wurde $ {FUNCNAME [$ i]} aus der Datei $ {BASH_SOURCE [$ i + 1]} unter der Zeilennummer $ {BASH_LINENO [$ i]} aufgerufen. Der integrierte Anrufer zeigt anhand dieser Informationen den aktuellen Aufrufstapel an.

Wenn auf Bash-Arrays ohne Index zugegriffen wird, $FUNCNAMEwird das erste Element des Arrays zurückgegeben. In einfachen Fällen wird daher der Name der sofort aktuellen Funktion angegeben, es enthält jedoch auch alle anderen Funktionen im Aufrufstapel. Beispielsweise:

# 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

Wird ausgegeben:

$ bash foobar
In function foo: FUNCNAME=foo foobar main
foobar
In function foobar: FUNCNAME=foobar main
bschlueter
quelle
6
Ich verstehe es immer noch nicht. Warum das hinzufügen, [0]wenn es durch den Zugriff auf die nicht dekorierte Variable impliziert wird?
Tom Hale
15
Weil es täuscht und den tatsächlichen Typ der Variablen nicht kennt? Sicher, es ist nicht immer notwendig, aber wie viele andere Bash-Ismen ist es eine faule Konvention. Besser explizit als mehrdeutig.
bschlueter
36

Ich ${FUNCNAME[0]}drucke den aktuellen Funktionsnamen

Grünspan
quelle
@bschlueter, aber wenn Sie auf ein Array verweisen, ohne es wie ein Array in Bash zu behandeln, wird nur der erste Wert gedruckt. Wie ist die akzeptierte Antwort daher falsch?
Alexej Magura
4
Sicher, und das ist praktisch, aber für Wartung und Tests schrecklich. Sei nicht faul, sei explizit.
bschlueter
1

Ein anderes Beispiel:

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

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

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

Wird ausgegeben:

begin main
foo fuction begins
foobar fuction begins
end main
Mickey White
quelle
-1

Der einfachste Weg, um den Funktionsnamen zu erhalten (aus einer Funktion heraus)

echo $0
jasonleonhard
quelle
Bitte hören Sie ###auf, Ihre Antworten zu missbrauchen .
Marcin Orlowski
@MarcinOrlowski Geht es dir gut? Klingt so, als könntest du eine Umarmung gebrauchen.
Jasonleonhard