bash:从“-x”回显中转义单独的行

bash:从“-x”回显中转义单独的行

在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 localoptionsin 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_fnuntrace_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

相关内容