如何从函数内部确定函数名称

时间:2009-12-02 21:29:30

标签: bash function

如果我有一个Bash脚本,如:

#!/bin/bash

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

有没有办法做到这一点?这可以在帮助消息中使用,例如

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

只有在这种情况下我想要的不是$0,这是脚本的文件名。

5 个答案:

答案 0 :(得分:182)

您可以使用${FUNCNAME[0]}中的bash来获取函数名称。

答案 1 :(得分:65)

来自Bash Reference Manual

  

FUNCNAME

     

一个数组变量,包含当前在执行调用堆栈中的所有shell函数的名称。索引为0的元素是当前正在执行的shell函数的名称。最底部的元素(索引最高的元素)是“main”。此变量仅在执行shell函数时存在。对FUNCNAME的分配无效并返回错误状态。如果未设置FUNCNAME,则会丢失其特殊属性,即使它随后被重置。

     

此变量可与BASH_LINENO和BASH_SOURCE一起使用。 FUNCNAME的每个元素在BASH_LINENO和BASH_SOURCE中都有对应的元素来描述调用堆栈。例如,$ {FUNCNAME [$ i]}是从行号$ {BASH_LINENO [$ i]}的$ {BASH_SOURCE [$ i + 1]}调用的。内置调用者使用此信息显示当前调用堆栈。

当没有索引访问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

答案 2 :(得分:32)

我使用${FUNCNAME[0]}打印当前功能名称

答案 3 :(得分:5)

(从函数内部)获取函数名称的最简单方法取决于所使用的shell:

Zsh版本

someFunctionName() {
   echo $funcstack[1]
}

bash版本

someFunctionName() {
   echo ${FUNCNAME[0]}
}

两者

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
}

答案 4 :(得分: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