【发布时间】:2017-04-15 03:10:35
【问题描述】:
我正在尝试为 bash 编写一个带有各种样式选项的彩色输出库,允许使用重定向进行着色和样式设置。
例如
echo "Red" | red输出红色文字
和
echo "Bold" | bold 输出粗体文本
和
echo "Yellow bold" | yellow | bold 输出粗体黄色文本
目前我写的代码如下:
#shellcheck shell=bash
# set debug
# set -o xtrace
# number of colors supported
__colors=$(tput colors 2> /dev/null)
# colors
__black="$(tput setaf 0)"
__red="$(tput setaf 1)"
__green="$(tput setaf 2)"
__yellow="$(tput setaf 3)"
__blue="$(tput setaf 4)"
__magenta="$(tput setaf 5)"
__cyan="$(tput setaf 6)"
__white="$(tput setaf 7)"
# style
__default="$(tput sgr0)"
__bold="$(tput bold)"
__underline="$(tput smul)"
function has_colors() {
COLOR=${COLOR:-auto}
if [[ $COLOR = 'never' ]]; then
return 1
elif [[ $COLOR = 'always' ]]; then
return 0
else
# check if stoud is terminal and terminal supports colors
[[ -t 1 ]] && \
[[ -n $__colors ]] && \
[[ $__colors -ge 8 ]]
fi
}
function __style() {
read -r input
if has_colors; then
echo -e "$1" "$input" "$__default"
else
echo -e "$input"
fi
}
function black() {
__style "$__black"
}
function red() {
__style "$__red"
}
function green() {
__style "$__green"
}
function yellow() {
__style "$__yellow"
}
function blue() {
__style "$__blue"
}
function magenta() {
__style "$__magenta"
}
function cyan() {
__style "$__cyan"
}
function white() {
__style "$__white"
}
function bold() {
__style "$__bold"
}
function underline() {
__style "$__underline"
}
设置 COLOR=always 始终使用转义码输出。另一方面 COLOR=auto 执行一些检查以确保当前标准输出是终端并且终端支持颜色。
问题是使用多个样式选项似乎不起作用。它总是应用最后一个样式选项。例如:
echo "Yellow bold" | yellow | bold 输出粗体文本,但不是黄色。
另一方面:
echo "Bold yellow" | bold | yellow 输出黄色文本,但不是粗体。
有趣的是;设置 COLOR=always 似乎工作得很好。所以看起来我执行的测试是否 stdout 是终端 [[ -t 1 ]] 导致了这种情况。我不确定是否是因为该测试存在某种延迟。但是当我删除[[ -t 1 ]] 位时,它可以工作。
知道如何实现这一目标吗?不是 Bash 专家,也不是 shell 如何解决这个问题的专家。这里很混乱。
【问题讨论】:
-
问题是
yellow | bold中,yellow的stdout不是tty。您应该在主脚本中检查一次并设置一个所有函数都使用的变量,而不是检查每个颜色函数 -
@那个其他人,这正是我检查它的原因。如果我检查一次并将输出重定向到一个文件,它将带有颜色转义码。我不想要的
-
查看 set -xv 输出,您的问题似乎来自这样一个事实,即粗体(假设它是第二个)在样式中的 echo -e 行之前被调用并接收原始副本字符串,因此您可以在中间进行任意数量的更改,结果将始终是标准文本加粗。不知何故,您需要让每个管道依次接收数据(不确定最佳方法)。你可以看看wait命令??
-
当您确实需要某种 三 路区分(终端 vs 文件 vs 管道)时,您正在进行双向区分(终端与非终端)。
标签: linux bash shell pipe echo