bash 中的 $PS4 - 如何重现 GNU 文档中提到的“间接级别”行为?

bash 中的 $PS4 - 如何重现 GNU 文档中提到的“间接级别”行为?

我正在读GNU 文档,我将以下句子视为 定义的一部分PS4

扩展值的第一个字符根据需要被复制多次,以指示多个间接级别。默认为“+”。

我将此解释为我将+在代码中看到每个抽象级别的符号。我想在我的 shell 中重现这种行为,所以我编写了以下代码:

#!/usr/bin/env bash

function baz() {
  echo "inside baz"
}

function foo() {
  echo "inside foo";
  baz;
}

function bar() {
  echo "inside bar";
  foo;
}

set -x;

bar;

由于bar调用foofoo调用baz,我预计最多有 3 级间接,因此我预计会看到类似以下(或类似)的输出:

+ bar
+ echo 'inside bar'
inside bar
++ foo
++ echo 'inside foo'
inside foo
+++ baz
+++ echo 'inside baz'
inside baz

然而,我所看到的并非如此。相反,我看到:

+ bar
+ echo 'inside bar'
inside bar
+ foo
+ echo 'inside foo'
inside foo
+ baz
+ echo 'inside baz'
inside baz

我是否误解了“间接级别”在这种情况下的含义,或者我只是未能正确重现所述间接级别?

答案1

正如当前接受的答案告诉您的那样,该级别与通过评估和采购增加的嵌套级别相关。它还可以通过命令替换来增加。

PS4='+ '
echo hello > world
set -x
wc -l $(ls -tc | head -1)

给出

++ ls -tc
++ head -1
+ wc -l world
1 world

如果您对函数深度感兴趣,那么您可以使用数组FUNCNAME。例如

PS4='+ ${_plus:0:${#FUNCNAME[@]}}${FUNCNAME[0]} '
_plus='================='
bar

其工作原理如下。${#FUNCNAME[@]} 扩展到数组中的元素数量FUNCNAME。由于当前正在调用的每个函数在数组中都有一个元素,因此这就是函数深度。然后使用该值从 中选择前 N 个字符$_plus,将其设置为符号序列=。中的字符数量$_plus是一种权衡。您需要足够的内容来显示您的函数嵌套,但如果您有深层嵌套(也许您有递归函数),您也希望避免提示变得愚蠢地长。添加${FUNCNAME[0]}显示当前功能。可以$FUNCNAME仅引用数组的顶部元素,但如果始终将数组作为数组访问,将标量作为标量访问,则会更清楚。

根据 OP 的定义foobarbaz给了你

$ bar
+  bar
+ =bar echo 'inside bar'
inside bar
+ =bar foo
+ ==foo echo 'inside foo'
inside foo
+ ==foo baz
+ ===baz echo 'inside baz'
inside baz

因此,+该行开头的 告诉您 eval/source/command 替换嵌套级别,等号告诉您函数嵌套级别,然后您就有了所在的函数名称。

添加LINENOBASH_SOURCE也是需要考虑添加到 PS4 提示符中的内容。

答案2

间接寻址与您观察到的函数无关,而是与 相关eval,如以下示例所示:

#!/usr/bin/env bash
set -x
echo 1
eval "echo 2"
eval 'eval "echo 3"'

这应该发出类似的东西

+ echo 1
1
+ eval 'echo 2'
++ echo 2
2
+ eval 'eval "echo 3"'
++ eval 'echo 3'
+++ echo 3
3

而且,正如 muru 指出的那样,还提供了源文件:

$ cat code
echo help
source code
$ bash -x code

希望您的control+c已准备好并热身...

相关内容