Come determinare il nome della funzione dall'interno di una funzione


163

Se ho uno script Bash come:

#!/bin/bash

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

C'è un modo per fare questo? Questo potrebbe essere usato in messaggi di aiuto come

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

Solo in questo caso ciò che volevo non è $0, che è il nome del file dello script.


2
Correlati: framework di registrazione Bash che utilizza FUNCNAMEarray e altre variabili Bash: github.com/codeforester/base/blob/master/lib/stdlib.sh . Vedi funzioni log_debug_entere log_debug_leavein particolare.
codeforester

Risposte:


236

È possibile utilizzare ${FUNCNAME[0]}in bashper ottenere il nome della funzione.


79

Dal manuale di riferimento di Bash :

FUNCNAME

Una variabile di matrice contenente i nomi di tutte le funzioni della shell attualmente nello stack delle chiamate di esecuzione. L'elemento con indice 0 è il nome di qualsiasi funzione shell attualmente in esecuzione. L'elemento più in basso (quello con l'indice più alto) è "principale". Questa variabile esiste solo quando è in esecuzione una funzione shell. Le assegnazioni a FUNCNAME non hanno alcun effetto e restituiscono uno stato di errore. Se FUNCNAME non è impostato, perde le sue proprietà speciali, anche se viene successivamente ripristinato.

Questa variabile può essere utilizzata con BASH_LINENO e BASH_SOURCE. Ogni elemento di FUNCNAME ha elementi corrispondenti in BASH_LINENO e BASH_SOURCE per descrivere lo stack di chiamate. Ad esempio, $ {FUNCNAME [$ i]} è stato chiamato dal file $ {BASH_SOURCE [$ i + 1]} al numero di riga $ {BASH_LINENO [$ i]}. Il chiamante incorporato visualizza lo stack di chiamate corrente utilizzando queste informazioni.

Quando si accede a array bash senza un indice, verrà restituito il primo elemento dell'array, quindi $FUNCNAMEfunzionerà in casi semplici per fornire il nome della funzione immediatamente corrente, ma contiene anche tutte le altre funzioni nello stack di chiamate. Per esempio:

# 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

Uscita:

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

6
Ancora non capisco. Perché aggiungere il [0]se è implicito accedendo alla variabile non decorata?
Tom Hale,

15
Perché è ingannevole e ignaro del tipo reale della variabile? Certo, non è sempre necessario, ma come molti altri bash-ismi, è una convenzione pigra. Meglio essere espliciti che ambigui.
bschlueter,

36

Uso ${FUNCNAME[0]}per stampare il nome della funzione corrente


@bschlueter ma quando fai riferimento a una matrice senza trattarla come una matrice in Bash, stampa solo il primo valore; quindi, come è errata la risposta accettata?
Alexej Magura,

4
Sicuro, e questo è conveniente, ma terribile per la manutenzione e i test. Non essere pigro, sii esplicito.
bschlueter

1

Un altro esempio:

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

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

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

Uscita:

begin main
foo fuction begins
foobar fuction begins
end main

-1

Il modo più semplice per ottenere il nome della funzione (dall'interno di una funzione)

echo $0

Per favore, smetti di abusare delle ###tue risposte.
Marcin Orlowski,

@MarcinOrlowski Stai andando bene? Sembra che potresti usare un abbraccio.
jasonleonhard,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.