在 bash 中:不使用调试陷阱来处理每个命令行?

在 bash 中:不使用调试陷阱来处理每个命令行?

我的 bash 环境中内置了一个复杂的机制,当提示符生成时,以及当用户按 Enter 键开始处理命令时,该机制都需要执行几个脚本。我给出一个过于简单的描述:

调试陷阱以相当有限的方式实现这一点:每次执行语句时它都会触发。

trap 'echo $BASH_COMMAND' DEBUG  # example only

不幸的是,这意味着当我输入以下内容时:

sleep 1; sleep 2; sleep 3

我没有处理包含整行的 $BASH_COMMAND,而是在三个不同的陷阱中得到了三个睡眠。更糟糕的是:

sleep 1 | sleep 2 | sleep 3

在管道设置时触发所有三个 - 在 sleep 1 开始执行之前,输出可能会让您相信 sleep 3 正在运行。

我需要一种方法来在开始时就执行脚本,处理整个命令,并且我宁愿它不在运行提示命令时触发,但如果必须的话我可以处理它。

答案1

不是很漂亮,但如果你真的需要这个,你可以PROMPT_COMMAND在调试陷阱之外使用它来摆脱额外的调用:

trap 'debug_hook' DEBUG

debug_hook()
{ 
  [ -n "$debug_hook_on" ] || return 
  debug_hook_on="" 
  echo hook             # cmds to run ...
}

PROMPT_COMMAND='debug_hook_on=1'

现在:

$ echo 1 ; echo 2 | cat
hook
1
2

但我们仍然无法访问整个输入行:$BASH_COMMAND只是echo 1


另一个灵感来自本文是使用 readline 绑定来访问整行:

$ bind -x '"\C-o":hook'
$ hook(){ echo "hook: $READLINE_LINE";  }
$ bind 'RETURN: "\C-o\n"'

现在它可以工作了:

hook: echo 1; echo 2
$ echo 1; echo 2
1
2

不过要记住一件事:对于多行输入,它会为每一行调用一次,这可能不是您想要的(可以结合使用两种方法)。

相关内容