Como determinar o nome da função de dentro de uma função

163

Se eu tiver um script Bash como:

#!/bin/bash

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

Há alguma maneira de fazer isso? Isso pode ser usado em mensagens de ajuda como

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

Somente neste caso o que eu queria não era $0, qual é o nome do arquivo do script.

Yan
fonte
2
Relacionado: Estrutura de log do Bash que usa FUNCNAMEmatriz e outras variáveis ​​do Bash: github.com/codeforester/base/blob/master/lib/stdlib.sh . Veja funções log_debug_entere log_debug_leaveem particular.
codeforester 08/04/19

Respostas:

236

Você pode usar ${FUNCNAME[0]}em bashobter o nome da função.

TheBonsai
fonte
79

No Manual de Referência do Bash :

FUNCNAME

Uma variável de matriz que contém os nomes de todas as funções de shell atualmente na pilha de chamadas de execução. O elemento com índice 0 é o nome de qualquer função shell em execução no momento. O elemento mais baixo (aquele com o índice mais alto) é "principal". Essa variável existe apenas quando uma função shell está em execução. As atribuições a FUNCNAME não têm efeito e retornam um status de erro. Se FUNCNAME estiver desativado, ele perderá suas propriedades especiais, mesmo que seja redefinido posteriormente.

Essa variável pode ser usada com BASH_LINENO e BASH_SOURCE. Cada elemento de FUNCNAME possui elementos correspondentes em BASH_LINENO e BASH_SOURCE para descrever a pilha de chamadas. Por exemplo, $ {FUNCNAME [$ i]} foi chamado a partir do arquivo $ {BASH_SOURCE [$ i + 1]} na linha número $ {BASH_LINENO [$ i]}. O chamador interno exibe a pilha de chamadas atual usando essas informações.

Quando as matrizes bash são acessadas sem um índice, o primeiro elemento da matriz será retornado; portanto $FUNCNAME, funcionará em casos simples para fornecer o nome da função imediatamente atual, mas também conterá todas as outras funções na pilha de chamadas. Por exemplo:

# 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

Saída:

$ bash foobar
In function foo: FUNCNAME=foo foobar main
foobar
In function foobar: FUNCNAME=foobar main
bschlueter
fonte
6
Eu ainda não entendi. Por que adicionar o [0]se está implícito acessando a variável não decorada?
Tom Hale
15
Porque é enganoso e ignorante do tipo real da variável? Claro, nem sempre é necessário, mas, como muitos outros festivais, é uma convenção preguiçosa. Melhor ser explícito do que ambíguo.
precisa saber é o seguinte
36

Eu uso ${FUNCNAME[0]}para imprimir o nome da função atual

Verdigrass
fonte
@bschlueter mas quando você faz referência a uma matriz sem tratá-la como uma matriz no Bash, ela apenas imprime o primeiro valor; portanto, como a resposta aceita está incorreta?
Alexej Magura
4
Claro, e isso é conveniente, mas terrível para manutenção e testes. Não seja preguiçoso, seja explícito.
precisa saber é o seguinte
1

Outro exemplo:

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

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

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

Saída:

begin main
foo fuction begins
foobar fuction begins
end main
Mickey Branco
fonte
-1

A maneira mais simples de obter o nome da função (de dentro de uma função)

echo $0
jasonleonhard
fonte
Pare de abusar ###nas suas respostas.
Marcin Orlowski 28/06
@MarcinOrlowski Você está bem? Parece que você poderia usar um abraço.
jasonleonhard 28/06