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

Yan*_*Yan 142 bash function

如果我有这样的BASH脚本:

#!/bin/bash

f() {
  # echo function name, "f" in this case
}
Run Code Online (Sandbox Code Playgroud)

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

printf "Usage: %s: blah blah blah \n" $(basename $0) >&2; 
Run Code Online (Sandbox Code Playgroud)

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

The*_*sai 203

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

  • zsh 中的 `funcstack`。 (4认同)

bsc*_*ter 71

Bash参考手册:

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
Run Code Online (Sandbox Code Playgroud)

将输出:

$ bash foobar
In function foo: FUNCNAME=foo foobar main
foobar
In function foobar: FUNCNAME=foobar main
Run Code Online (Sandbox Code Playgroud)

  • 因为它对变量的实际类型具有欺骗性和无知性?当然,它并不总是必要的,但像许多其他的bash-isms一样,这是一个懒惰的惯例.最好是明确而不是模棱两可. (13认同)
  • 我还是不明白.如果通过访问未修饰的变量隐含的话,为什么要添加`[0]`? (5认同)

Ver*_*ass 34

${FUNCNAME[0]}用来打印当前的函数名称

  • 当然,这很方便,但维护和测试很糟糕.不要偷懒,要明确. (4认同)

jas*_*ard 11

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

zsh版本

someFunctionName() {
   echo $funcstack[1]
}
Run Code Online (Sandbox Code Playgroud)

bash 版本

someFunctionName() {
   echo ${FUNCNAME[0]}
}
Run Code Online (Sandbox Code Playgroud)

两个都

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
}
Run Code Online (Sandbox Code Playgroud)

  • 请停止在您的答案中滥用“###”。 (2认同)
  • 也许‘###’不应该存在于平台上。为什么要提供在任何情况下都不会使用的东西? (2认同)
  • 连续使用 awk 来确定 bash 与 zsh 的四进程管道有问题?天啊。`test -n "$ZSH_VERSION" && echo $funcstack[1]; test -n "$BASH_VERSION" && echo ${FUNCNAME[0]}"`。拯救地球。今天保存四个进程:-) (2认同)