zsh 中函数的调用上下文:相当于 bash `caller`

Tom*_*ale 9 shell debugging zsh function

在 bash 中,我可以写:

caller 0
Run Code Online (Sandbox Code Playgroud)

并接收调用者上下文的:

  • 电话号码
  • 功能
  • 脚本名称

这对于调试非常有用。鉴于:

yelp () { caller 0; }
Run Code Online (Sandbox Code Playgroud)

然后我可以写yelp来看看到达了哪些代码行。

我可以实现caller 0bash如下:

echo "${BASH_LINENO[0]} ${FUNCNAME[1]} ${BASH_SOURCE[1]"
Run Code Online (Sandbox Code Playgroud)

我怎样才能获得相同的输出caller 0zsh

mur*_*uru 15

我认为没有等效的内置命令,但是可以使用来自zsh/Parameter 模块的这四个变量的某些组合:

funcfiletrace
Run Code Online (Sandbox Code Playgroud)

此数组包含调用当前函数、源文件或(如果EVAL_LINENO已设置)eval命令的点的绝对行号和相应的文件名 。该数组的长度与funcsourcetraceand相同functrace,但不同之处在于 funcsourcetrace行和文件是调用点,而不是定义点,不同之处functrace在于所有值都是文件中的绝对行号,而不是相对于函数的开始,如果有的话。

funcsourcetrace
Run Code Online (Sandbox Code Playgroud)

此数组包含 定义当前正在执行的函数、源文件和(如果EVAL_LINENO已设置)eval命令的点的文件名和行号。行号是“ function name”或“ name ()”开始的行。在自动加载函数的情况下,行号报告为零。每个元素的格式是filename:lineno.

对于从原生 zsh 格式的文件自动加载的函数,其中只有函数的主体出现在文件中,或者对于已由source或 ' .' 内置函数执行的文件,跟踪信息显示为filename:0,因为整个文件是定义。加载函数时,源文件名被解析为绝对路径,否则解析为它的路径。

大多数用户会对funcfiletrace数组中的信息感兴趣 。

funcstack
Run Code Online (Sandbox Code Playgroud)

此数组包含函数、源文件和(如果 EVAL_LINENO已设置)eval命令的名称。目前正在执行。第一个元素是使用参数的函数名称。

标准 shell 数组zsh_eval_context可用于确定在每个深度执行的 shell 构造的类型:但是请注意,这是相反的顺序,最近的项目最后,并且更详细,例如包括一个条目顶层,主要的 shell 代码以交互方式或从脚本执行,它不存在于$funcstack.

functrace
Run Code Online (Sandbox Code Playgroud)

该数组包含与当前正在执行的函数对应的调用者的名称和行号。每个元素的格式是name:lineno. 还显示了源文件的调用者;调用者是执行sourceor ' .' 命令的点。

比较:

foo.bash

funcfiletrace
Run Code Online (Sandbox Code Playgroud)

foo.zsh

funcsourcetrace
Run Code Online (Sandbox Code Playgroud)

结果:

funcstack
Run Code Online (Sandbox Code Playgroud)

因此,相应的值在${funcfiletrace[1]}和 中${funcstack[-1]}。修改yelp为:

functrace
Run Code Online (Sandbox Code Playgroud)

输出是:

#! /bin/bash
yelp() {
    caller 0
}

foo () {
    yelp
}

foo
Run Code Online (Sandbox Code Playgroud)

这非常接近 bash 的

#! /bin/zsh
yelp() {
    print -l -- $funcfiletrace - $funcsourcetrace - $funcstack - $functrace
}

foo () {
    yelp
}

foo
Run Code Online (Sandbox Code Playgroud)