bash:从`-x` 回显中转义单个行

cla*_*cke 14 shell bash debugging

在 bash 中,当使用该-x选项运行时,是否可以免除单个命令的回显?

我试图使输出尽可能整洁,所以我在带有set +x. 但是,行set +x本身仍然被回显,并且不会向输出添加任何有价值的信息。

我记得在过去糟糕的.bat日子里,当运行时echo on,个别行可以通过以@. bash 中是否有任何等价物?

#!/bin/bash -x

function i_know_what_this_does() {
  (
    set +x
    echo do stuff
  )
}

echo the next-next line still echoes 'set +x', is that avoidable?
i_know_what_this_does
echo and we are back and echoing is back on
Run Code Online (Sandbox Code Playgroud)

运行上述程序时,输出为:

+ echo the next-next line still echoes 'set +x,' is that 'avoidable?'
the next-next line still echoes set +x, is that avoidable?
+ i_know_what_this_does
+ set +x
do stuff
+ echo and we are back and echoing is back on
and we are back and echoing is back on
Run Code Online (Sandbox Code Playgroud)

Sté*_*las 25

xtrace输出转到 stderr,因此您可以重定向stderr/dev/null

i_know_what_this_does() {
  echo do stuff
} 2> /dev/null
Run Code Online (Sandbox Code Playgroud)

如果您仍然想查看函数内部运行的命令的错误,您可以这样做

i_know_what_this_does() (
  { set +x; } 2> /dev/null # silently disable xtrace
  echo do stuff
)
Run Code Online (Sandbox Code Playgroud)

请注意使用(...)而不是{...}通过子shell 为该函数提供本地范围。bash,因为 4.4 版现在支持local -像在 Almquist shell 中那样为函数设置本地选项(类似于set -o localoptionsin zsh),因此您可以通过执行以下操作来避免子shell:

i_know_what_this_does() {
  { local -; set +x; } 2> /dev/null # silently disable xtrace
  echo do stuff
}
Run Code Online (Sandbox Code Playgroud)

bash4.0 到 4.3的替代方法是使用该$BASH_XTRACEFD变量并/dev/null为此打开一个专用的文件描述符:

exec 9> /dev/null
set -x
i_know_what_this_does() {
  { local BASH_XTRACEFD=9; } 2> /dev/null # silently disable xtrace
  echo do stuff
}
Run Code Online (Sandbox Code Playgroud)

由于bash缺乏使用close-on-exec标志标记 fd 的能力,因此具有将该 fd 泄漏给其他命令的副作用。

另见本locvar.sh其中包含了一些功能来实现本地对POSIX脚本变量和函数范围,并与提供trace_fnuntrace_fn功能,使其X跟踪d与否。