我有一个 Bash 脚本,它作为一项作业以交互方式运行cron
。当交互运行时,它会在终端上输出彩色文本。然而,当运行时cron
它没有终端,因此我[1;31m
在输出中得到大量类似的结果。
如果输出设备不支持转义码,Bash 有没有办法告诉它吞掉转义码?
这与如何检查 bash 是否可以打印颜色这是关于检查条件。但是,我希望在调用echo
或printf
同时保留颜色的双重功能或不取决于输出设备时尽可能少地进行更改。
答案1
检查您是否正在打印到终端。当你告诉GNUls
和 GNU等程序时,它们就会这么做。grep
--color=auto
即使您正在打印到终端,理论上,它也可能无法理解变色转义序列。实际上,所有常见和最不常见的终端都理解这些序列:我见过的所有 X11 终端仿真器、screen、tmux、Linux 控制台、*BSD 控制台、PuTTY、rxvt、Console2、ConEmu、 ……
normal=
green=
…
if [ -t 1 ]; then
normal=$'\e[0m'
green=$'\e32m'
…
fi
…
echo "foobar ${green}OK${normal}"
该测试[ -t 1 ]
针对标准输出和[ -t 2 ]
标准错误。
在不支持$'…'
扩展的 shell 中,您可以使用以下命令生成可移植的转义字符esc=$(echo _ | tr _ '\033')
答案2
不完全是吞咽,但你可以通过参数扩展来删除它们:
str='Hello \e[31mc\e[32mo\e[33ml\e[34mo\e[35mr\e[m world'
# colorful output
echo -e "$str"
# colorless output
echo -e "${str//\\e\[+([0-9;])m}"
上面的内容bash
需要extglob
打开 shell 选项。 ( shopt -s extglob
)
为了方便使用,定义一个函数:
function ecco() { [ -t 1 ] && echo -e "$1" || echo -e "${1//\\e\[+([0-9;])m}"; }
然后你只需调用它:
ecco 'Hello \e[31mc\e[32mo\e[33ml\e[34mo\e[35mr\e[m world'
要检查它是否有效,只需重定向其输出,颜色就会消失:
ecco 'Hello \e[31mc\e[32mo\e[33ml\e[34mo\e[35mr\e[m world' | cat
答案3
您应该在脚本中检查它是否以交互方式运行?
http://www.gnu.org/software/bash/manual/html_node/Is-this-Shell-Interactive_003f.html
引号:
6.3.2 这个 Shell 是交互式的吗?
要确定启动脚本中的 Bash 是否以交互方式运行,请测试“-”特殊参数的值。当 shell 是交互式的时它包含 i。例如:
case "$-" in *i*) echo This shell is interactive ;; *) echo This shell is not interactive ;; esac
或者,启动脚本可以检查变量 PS1;它在非交互式 shell 中未设置,并在交互式 shell 中设置。因此:
if [ -z "$PS1" ]; then echo This shell is not interactive else echo This shell is interactive fi
如果是交互式的,则定义一组变量为“_escape_codes_”,如果不是,则定义为“”,并使用这些变量对脚本中的输出进行着色(在交互式环境中,它们将具有转义码,在非交互式环境中,它们将添加与正文无关)。
前任:
case "$-" in
*i*) _bold_="$(printf '\033[1m')"
_norm_="$(printf '\033[0m')"
;;
*) _bold_=""
_norm_=""
;;
esac
echo "this ${_bold_}text${_norm_} is important"