如果我有一个Bash脚本:

#!/bin/bash

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

有什么办法可以做到吗?这可以在帮助消息中使用,例如

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

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


当前回答

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

Zsh 版本

someFunctionName() {
   echo $funcstack[1]
}

Bash的版本

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

Both

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
}

更健壮的版本

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

其他回答

另一个例子:

# 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

来自Bash参考手册:

FUNCNAME An array variable containing the names of all shell functions currently in the execution call stack. The element with index 0 is the name of any currently-executing shell function. The bottom-most element (the one with the highest index) is "main". This variable exists only when a shell function is executing. Assignments to FUNCNAME have no effect and return an error status. If FUNCNAME is unset, it loses its special properties, even if it is subsequently reset. This variable can be used with BASH_LINENO and BASH_SOURCE. Each element of FUNCNAME has corresponding elements in BASH_LINENO and BASH_SOURCE to describe the call stack. For instance, ${FUNCNAME[$i]} was called from the file ${BASH_SOURCE[$i+1]} at line number ${BASH_LINENO[$i]}. The caller builtin displays the current call stack using this information.

在没有索引的情况下访问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

我使用${FUNCNAME[0]}打印当前函数名

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

Zsh 版本

someFunctionName() {
   echo $funcstack[1]
}

Bash的版本

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

Both

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
}

更健壮的版本

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

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