在bash中,当使用该-x
选项运行时,是否可以免除单个命令的回显?
我试图使输出尽可能整洁,因此我在子 shell 中运行脚本的某些部分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
运行上述命令时,输出为:
+ 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
答案1
xtrace
输出转到 stderr,因此您可以重定向stderr
到/dev/null
:
i_know_what_this_does() {
echo do stuff
} 2> /dev/null
如果您仍然想查看函数内运行的命令的错误,您可以这样做
i_know_what_this_does() (
{ set +x; } 2> /dev/null # silently disable xtrace
echo do stuff
)
请注意,使用(...)
代替{...}
通过子 shell 为该函数提供本地作用域。bash
,由于版本 4.4 现在支持local -
像在 Almquist shell 中一样将选项设置为函数的本地选项(类似于set -o localoptions
in zsh
),因此您可以通过执行以下操作来避免使用子 shell:
i_know_what_this_does() {
{ local -; set +x; } 2> /dev/null # silently disable xtrace
echo do stuff
}
4.0 到 4.3的替代bash
方法是使用变量并为此$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
}
由于bash
缺乏用 来标记 fd 的能力执行时关闭标志,但这会产生将该 fd 泄漏给其他命令的副作用。
另请参阅此locvar.sh其中包含一些要实现的函数当地的POSIX 脚本中变量和函数的作用域,并且还提供了trace_fn
和untrace_fn
函数来使它们跟踪d 与否。
答案2
set +x
打印的原因是这set -x
意味着“打印您将要运行的命令,并进行扩展,在运行之前。因此,shell 不知道您希望它不打印内容,直到它打印了告诉它不要打印内容的行之后。据我所知,没有办法阻止这种情况的发生。
答案3
这是您一直在寻找的解决方案:
function xtrace() {
# Print the line as if xtrace was turned on, using perl to filter out
# the extra colon character and the following "set +x" line.
(
set -x
# Colon is a no-op in bash, so nothing will execute.
: "$@"
set +x
) 2>&1 | perl -ne 's/^[+] :/+/ and print' 1>&2
# Execute the original line unmolested
"$@"
}
原始命令在身份转换下在同一 shell 中执行。在运行之前,您会获得参数的非递归 xtrace。这允许您 xtrace 您关心的命令,而不用每个“echo”命令的重复副本向 stederr 发送垃圾邮件。
# Example
echo "About to do something complicated ..."
xtrace do_something_complicated