202 votes

Comment déterminer le nom d'une fonction à l'intérieur d'une fonction

Si j'ai un script Bash comme :

#!/bin/bash

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

Existe-t-il un moyen de le faire ? Cela pourrait être utilisé dans des messages d'aide tels que

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

Seulement, dans ce cas, ce que je voulais n'est pas $0 qui est le nom de fichier du script.

2 votes

En rapport : Cadre de journalisation Bash qui utilise FUNCNAME et d'autres variables Bash : github.com/codeforester/base/blob/master/lib/stdlib.sh . Voir les fonctions log_debug_enter y log_debug_leave en particulier.

1 votes

Quelque chose pour un shell posix pur ?

0 votes

@Itération122442 : il semblerait qu'en dash on puisse utiliser $_ mais je ne pense pas que cela soit standardisé dans POSIX.

291voto

TheBonsai Points 3112

Vous pouvez utiliser ${FUNCNAME[0]} en bash pour obtenir le nom de la fonction.

1 votes

funcstack dans zsh.

96voto

bschlueter Points 2010

A partir de la Manuel de référence Bash :

NOM DE FONCTION

Variable de type tableau contenant les noms de toutes les fonctions de l'interpréteur de commandes se trouvant actuellement dans la pile d'appels de l'exécution. L'élément d'index 0 est le nom de toute fonction shell en cours d'exécution. L'élément le plus bas (celui qui a l'indice le plus élevé) est "main". Cette variable n'existe que lorsqu'une fonction shell est en cours d'exécution. Les affectations à FUNCNAME n'ont aucun effet et renvoient un statut d'erreur. Si FUNCNAME est désactivée, elle perd ses propriétés spéciales, même si elle est réinitialisée par la suite.

Cette variable peut être utilisée avec BASH_LINENO et BASH_SOURCE. À chaque élément de FUNCNAME correspondent des éléments dans BASH_LINENO et BASH_SOURCE pour décrire la pile d'appels. Par exemple, ${FUNCNAME[$i]} a été appelé à partir du fichier ${BASH_SOURCE[$i+1]} à la ligne ${BASH_LINENO[$i]}. Le builtin caller affiche la pile d'appels en cours à l'aide de ces informations.

Lorsque les tableaux bash sont accédés sans index, le premier élément du tableau est retourné, ainsi $FUNCNAME fonctionne dans les cas simples pour fournir le nom de la fonction en cours, mais elle contient également toutes les autres fonctions de la pile d'appels. Par exemple :

# 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

Sortie de secours :

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

38voto

Verdigrass Points 1

Utilizo ${FUNCNAME[0]} pour imprimer le nom de la fonction en cours

14voto

un5t0ppab13 Points 55

La manière la plus simple d'obtenir le nom de la fonction (à l'intérieur d'une fonction) dépend de l'interpréteur de commandes que vous utilisez :

Version de Zsh
someFunctionName() {
   echo $funcstack[1]
}
Version Bash
someFunctionName() {
   echo ${FUNCNAME[0]}
}
Les deux
someFunctionName() {
  currentShell=$(ps -p $$ | awk "NR==2" | awk '{ print $4 }' | tr -d '-')
  if [[ $currentShell == 'bash' ]]; then
    echo ${FUNCNAME[0]}
  elif [[ $currentShell == 'zsh' ]]; then
    echo $funcstack[1]
  fi
}
Une version plus robuste
columnX () {
    awk "{print \$$1}"
}
rowX () {
    awk "NR==$1"
}

checkShell() {
    ps -p $$ | columnX 4 | rowX 2 | tr -d - 
    # produces bash or zsh (or other shell name like fish)
}

showMethodName(){
    checkShell && echo ${FUNCNAME[0]} || echo $funcstack[1] 
}
showMethodName

2voto

Mickey White Points 11

Autre exemple :

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

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

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

Sortie de secours :

begin main
foo fuction begins
foobar fuction begins
end main

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X