如何在终端中添加颜色?

如何在终端中添加颜色?

我想使用 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[0mESC[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 分量的十进制表示。

您可以轻松地使用%dprintf十六进制转换为十进制。它看起来像这样:

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 位颜色,它可能会将您想要的颜色转换为最接近的颜色支持的调色板。

相关内容