我想使用 rgb(a) 十六进制代码在终端上显示颜色。我打算制作某种可以在括号内渲染颜色的程序,例如:[#FFFFFF]this is white text
答案1
您不需要专用的外部程序来在终端中显示颜色。如果终端支持颜色,那么它将对特定的控制序列做出反应,这些控制序列只不过是嵌入在要打印的文本的同一流中的字节序列。您可以使用echo
或 (更好的)printf
或者任何可以打印任意数据的东西。
许多在线资源涵盖了广泛分布的 8 种颜色和 8 种明亮的颜色(例子)。现代终端仿真器还支持24 位颜色;这就是你所需要的。我假设你的终端仿真器足够现代。
序列如下:
ESC[38;2;⟨r⟩;⟨g⟩;⟨b⟩m
设置 RGB 前景色ESC[48;2;⟨r⟩;⟨g⟩;⟨b⟩m
设置 RGB 背景颜色
其中ESC
表示转义字符(十进制值为 27、八进制为 33、十六进制为 1B 的字节),⟨r⟩
和⟨g⟩
分别⟨b⟩
为红色、绿色和蓝色的 8 位分量,写为十进制使用 ASCII 数字(因此范围是 0..255)。标准序列ESC[0m
或ESC[m
可用于将颜色(以及更多一般颜色)重置为终端认为的默认值。
上面的转义符 ( ESC
) 可以表示为\033
(八进制)\0x1B
或\x1b
(十六进制) ,\e
或者^[
其他方式。各种工具支持这些符号的各种子集。
如何printf
从 shell 打印彩色文本的示例:
printf '\e[38;2;240;100;200m\e[48;2;200;255;50mHello World!\e[0m\n'
# fg RRR GGG BBB bg RRR GGG BB reset
您希望以字符串形式提供前景色,格式如下[#FFFFFF]
。如果相关转义序列使用十六进制数,则将所需格式转换为可用的转义序列(例如使用)相对容易sed
。不幸的是,该序列必须使用 RGB 分量的十进制表示。
您可以轻松地使用%d
将printf
十六进制转换为十进制。它看起来像这样:
printf '\e[38;2;%d;%d;%dm%s\e[0m\n' 0x00 0xA0 0xFF 'Hello World!'
这些0x00 0xA0 0xFF
需要是单独的参数。从 的形式获取它们需要一些工作[#00A0FF]
,但这是可能的。如果您的目标是解析 形式的字符串[#FFFFFF]this is white text
,其中[#…]
始终位于开头,那么只需在 POSIX shell 中操作字符串即可完成(主要使用这些)。一个示例 shell 函数:
colprint() (
text="${1#'[#'??????']'}"
r="${1%"$text"}"
r="${r%']'}"
r="${r#'[#'}"
r="${r:-FFFFFF}"
b="${r#????}"
r="${r%??}"
g="${r#??}"
r="${r%??}"
printf '\e[38;2;%d;%d;%dm%s\e[0m\n' "0x$r" "0x$g" "0x$b" "$text"
)
进而:
colprint '[#FFFFFF]this is white text'
colprint '[#FF0000]this is red text'
colprint '[#BFFF00]this is lime text'
colprint 'white again (default)'
如果您想检测[#…]
行中的任何位置并用适当的转义序列替换它,那么建议使用更强大的工具。如果不是,从十六进制到十进制的转换sed
会更好。由于转换,我认为您需要更像的东西awk
。无论如何,原则上这似乎可以通过标准工具实现。既然您“打算制作某种程序”,我不会通过发布一个工作示例来夺走您的这种乐趣。:) 现在您知道要打印到终端的内容了。祝你好运!
注意,专用于显示颜色的外部程序可能不仅仅是像我们的colprint
函数一样直接生成转义序列。首先,它可能检查$TERM
并$COLORTERM
了解终端是否真的支持颜色以及支持的颜色数量;然后它可能会选择实际有效的序列。例如,如果它发现终端不支持 24 位颜色,它可能会将您想要的颜色转换为最接近的颜色支持的调色板。