Answers:
我认为没有等效的内置命令,但是可以使用zsh / Parameter模块中这四个变量的某种组合:
funcfiletrace
该数组包含绝对行号和相应点的文件名,该点是当前函数,源文件或(如果
EVAL_LINENO
已设置)eval
命令被调用的点。数组的长度与funcsourcetrace
和相同functrace
,但区别在于funcsourcetrace
行和文件是调用点,而不是定义点,并且区别functrace
在于所有值都是文件中的绝对行号,而不是相对于函数的开始(如果有)。funcsourcetrace
此数组包含的文件名,并且其中所述的功能,源文件,和点的行号(如果
EVAL_LINENO
是组)eval
被定义命令当前正在执行。行号是“function name
”或“name ()
”开始的行。对于自动加载的功能,行号报告为零。每个元素的格式为filename:lineno
。对于从本机zsh格式的文件自动加载的函数(该函数的主体仅出现在该文件中),或者对于已由
source
或'.
'内置文件执行的filename:0
文件,由于整个文件都是定义。加载函数时,源文件名将解析为绝对路径,否则将解析为该路径。大多数用户将对
funcfiletrace
数组中的信息感兴趣 。funcstack
该数组包含函数,源文件和(如果
EVAL_LINENO
已设置)eval
命令的名称。当前正在执行。第一个元素是使用参数的函数的名称。标准shell数组
zsh_eval_context
可用于确定在每个深度执行的shell构造的类型:但是请注意,这是相反的顺序,最新的项目在最后,并且更详细,例如,包括顶层,主要的shell代码是以交互方式或通过脚本执行的,而不在中$funcstack
。functrace
该数组包含与当前正在执行的功能相对应的调用方的名称和行号。每个元素的格式为
name:lineno
。还会显示源文件的调用方。调用者是执行“source
或.
”命令的地方。
比较:
foo.bash
:
#! /bin/bash
yelp() {
caller 0
}
foo () {
yelp
}
foo
foo.zsh
:
#! /bin/zsh
yelp() {
print -l -- $funcfiletrace - $funcsourcetrace - $funcstack - $functrace
}
foo () {
yelp
}
foo
结果:
$ bash foo.bash
7 foo foo.bash
$ zsh foo.zsh
foo.zsh:7
foo.zsh:10
-
foo.zsh:2
foo.zsh:6
-
yelp
foo
-
foo:1
foo.zsh:10
因此,相应的值在${funcfiletrace[1]}
和中${funcstack[-1]}
。修改yelp
为:
yelp() {
print -- $funcfiletrace[1] $funcstack[-1]
}
输出为:
foo.zsh:7 foo
这非常接近bash的
7 foo foo.bash
根据muru的回答,我实现了以下两个功能都可以使用的功能{ba,z}sh
:
$ cat yelp
#!/bin/zsh
# Say the file, line number and optional message for debugging
# Inspired by bash's `caller` builtin
# Thanks to https://unix.stackexchange.com/a/453153/143394
function yelp () {
# shellcheck disable=SC2154 # undeclared zsh variables in bash
if [[ $BASH_VERSION ]]; then
local file=${BASH_SOURCE[1]} func=${FUNCNAME[1]} line=${BASH_LINENO[0]}
else # zsh
emulate -L zsh # because we may be sourced by zsh `emulate bash -c`
# $funcfiletrace has format: file:line
local file=${funcfiletrace[1]%:*} line=${funcfiletrace[1]##*:}
local func=${funcstack[2]}
[[ $func =~ / ]] && func=source # $func may be filename. Use bash behaviour
fi
echo "${file##*/}:$func:$line $*" > /dev/tty
}
foo () { yelp; }
yelp
foo
输出为:
$ ./yelp
yelp::20
yelp:foo:19