Bash 流式命令替换输出到终端,不带静噪颜色
是否有一种方法可以在执行命令替换时以颜色显示其输出,同时仍将其存储到变量中?这主要是出于测试/调试目的,输出不会正常显示 如果我这样做:Bash 流式命令替换输出到终端,不带静噪颜色,bash,command-substitution,Bash,Command Substitution,是否有一种方法可以在执行命令替换时以颜色显示其输出,同时仍将其存储到变量中?这主要是出于测试/调试目的,输出不会正常显示 如果我这样做: output=$(some_command) if [ "$debug" ]; then echo "$output" fi …那么这很接近,但在以下几个方面不是我想要的: 即使该命令以其他方式向终端发出彩色输出,也会以黑白打印 输出仅在命令完成后显示,而不是在命令运行时显示 如何有条件地将输出流式传输到终端而不抑制颜色?要将命令的结果存储到变量,并
output=$(some_command)
if [ "$debug" ]; then
echo "$output"
fi
…那么这很接近,但在以下几个方面不是我想要的:
- 即使该命令以其他方式向终端发出彩色输出,也会以黑白打印
- 输出仅在命令完成后显示,而不是在命令运行时显示
如何有条件地将输出流式传输到终端而不抑制颜色?要将命令的结果存储到变量,并将其输出流式传输到控制台:
var=$(some_command | tee /dev/stderr)
如果要强制命令将其直接输出到TTY,从而在不在管道中时启用颜色输出,请使用expect
附带的工具unbuffer
:
var=$(unbuffer some_command | tee /dev/stderr)
所有这些都说明了:如果您只想有条件地显示长脚本的调试,那么最好将该条件放在脚本的顶部,而不是将其分散到任何地方。例如:
# put this once at the top of your script
set -o pipefail
if [[ $debug ]]; then
exec 3>/dev/stderr
else
exec 3>/dev/null
fi
# define a function that prepends unbuffer only if debugging is enabled
maybe_unbuffer() {
if [[ $debug ]]; then
unbuffer "$@"
else
"$@"
fi
}
# if debugging is enabled, pipe through tee; otherwise, use cat
capture() {
if [[ $debug ]]; then
tee >(cat >&3)
else
cat
fi
}
# ...and thereafter, when you want to hide a command's output unless debug is enabled:
some_command >&3
# ...or, to capture its output while still logging to stderr without squelching color...
var=$(maybe_unbuffer some_command | capture)
要将命令结果存储到变量并将其输出流式传输到控制台,请执行以下操作:
var=$(some_command | tee /dev/stderr)
如果要强制命令将其直接输出到TTY,从而在不在管道中时启用颜色输出,请使用expect
附带的工具unbuffer
:
var=$(unbuffer some_command | tee /dev/stderr)
所有这些都说明了:如果您只想有条件地显示长脚本的调试,那么最好将该条件放在脚本的顶部,而不是将其分散到任何地方。例如:
# put this once at the top of your script
set -o pipefail
if [[ $debug ]]; then
exec 3>/dev/stderr
else
exec 3>/dev/null
fi
# define a function that prepends unbuffer only if debugging is enabled
maybe_unbuffer() {
if [[ $debug ]]; then
unbuffer "$@"
else
"$@"
fi
}
# if debugging is enabled, pipe through tee; otherwise, use cat
capture() {
if [[ $debug ]]; then
tee >(cat >&3)
else
cat
fi
}
# ...and thereafter, when you want to hide a command's output unless debug is enabled:
some_command >&3
# ...or, to capture its output while still logging to stderr without squelching color...
var=$(maybe_unbuffer some_command | capture)
tee
是您的朋友。此外,通过查看命令的输出来确定命令是否失败也是。。。不是通常的做法;惯例是查看退出状态<代码>如果!输出=$(some_命令);然后回显“某些命令失败!”>&2;fi将存储输出并检查退出状态。@trysis,实际上,如果您正确使用了if
,通常根本不需要$?
——您可以直接测试退出状态,而不是存储后再测试。@trysis,…也就是说,如果您只想有条件地显示输出,如果启用了调试,我会将文件描述符重定向到控制台,如果未启用调试,则重定向到/dev/null,并将您只希望看到的内容复制到该FD。@trysis,Shell的问题是,它的向后兼容性可以追溯到20世纪70年代。当然,如果我们今天构建一个不需要运行旧代码的新shell,我们会做一些不同的事情,但是。。。沿着这条路走得太远,你就会得到zsh(只要有选择,zsh做的都是正确的事情,而不是兼容的事情,结果是那些过度习惯于使用它的人编写的代码在针对其他任何东西时都是一大堆微妙的错误,因为他们不习惯考虑这些问题).tee
是您的朋友。此外,通过查看命令的输出来确定命令是否失败也是。。。不是通常的做法;惯例是查看退出状态<代码>如果!输出=$(some_命令);然后回显“某些命令失败!”>&2;fi将存储输出并检查退出状态。@trysis,实际上,如果您正确使用了if
,通常根本不需要$?
——您可以直接测试退出状态,而不是存储后再测试。@trysis,…也就是说,如果您只想有条件地显示输出,如果启用了调试,我会将文件描述符重定向到控制台,如果未启用调试,则重定向到/dev/null,并将您只希望看到的内容复制到该FD。@trysis,Shell的问题是,它的向后兼容性可以追溯到20世纪70年代。当然,如果我们今天构建一个不需要运行旧代码的新shell,我们会做一些不同的事情,但是。。。沿着这条路走得太远,你就会得到zsh(只要有选择,zsh做的都是正确的事情,而不是兼容的事情,结果是那些过度习惯于使用它的人编写的代码在针对其他任何东西时都是一大堆微妙的错误,因为他们不习惯考虑这些问题)。我打算提出类似的建议,$(一些|命令| tee>(cat>/dev/stderr))
,即使本地文件系统中没有/dev/stderr
,它也会起作用。不过,它也有同样的TTY问题。我认为你是对的,我误解了question@chepner好电话;我在长格式扩展回答中加入了这一点,我打算提出类似的建议,$(some_command | tee>(cat>/dev/stderr))
,即使本地文件系统中没有/dev/stderr
,它也会起作用。不过,它也有同样的TTY问题。我认为你是对的,我误解了question@chepner好电话;我将其纳入了长格式扩展答案中