了解 ANSI 转义码的 color 设置

3,573 阅读6分钟

信令

在日常生活中,我们经常打电话。当拿起送受话器,话机便向交换机发出了摘机信息,紧接着我们就会听到一种连续的“嗡嗡”声,这是交换机发出的,告诉我们可以拨号的信息。当拨通对方后,又会听到“哒-哒-”的呼叫对方的声音,这是交换局发出的,告诉我们正在呼叫对方接电话的信息……。

这里所说的摘机信息、允许拨号的信息、呼叫对方的回铃信息等等,主要用于建立双方的通信关系,我们把这类信息称为信令。(信令是交换机之间通信的语言)

in-bind signling

中文翻译叫带内信令。上面说了信令是用来建立双方的通信关系的信息。而通信建立后传递的消息就是通信的内容。那么带内信令就是指信令和通信内容使用同一通道。具体原理和知识很复杂,这里只做了解。

ANSI 转义码

ANSI 转义序列是命令行终端下用来控制光标位置、字体颜色以及其他终端选项的一项 in-bind signaling 标准。通常是在文本中嵌入确定的字节序列(符合带内信令的定义),大部分以 ESC 转义字符和 "[" 字符开始,终端会把这些字节序列解释为相应的指令,而不是普通的字符编码

在终端中,ASCII编码中有些字符是不能用来打印显示的,比如 '\a' ( 0x7 ) 代表响铃,'\n' (0x0A) 代表换行,这些字符被称为控制符。控制符 '\e' (0x1B),这个字符代表 ESC ,即键盘上 ESC 按键的作用。ESC 是单词 escape 的缩写,即逃逸的意思。文本中出现这个转义字符,代表其后方的字符是 ANSI Escape code 编码

如果终端输出不支持 ANSI 转义码,那么可能会看下下面的信息:

ESC[1;Foreground
�[1;30m 30  �[1;30m 30  �[1;30m 30  �[1;30m 30  �[1;30m 30  �[1;30m 30  �[1;30m 30  �[1;30m 30  �[0m
�[1;31m 31  �[1;31m 31  �[1;31m 31  �[1;31m 31  �[1;31m 31  �[1;31m 31  �[1;31m 31  �[1;31m 31  �[0m
�[1;32m 32  �[1;32m 32  �[1;32m 32  �[1;32m 32  �[1;32m 32  �[1;32m 32  �[1;32m 32  �[1;32m 32  �[0m
...

ANSI color

ANSI Escape code编码中有专门控制字符颜色的控制符,例如:

\e[37;44;3;1m
  • \e 代表开始ANSI Escape code
  • [ 代表转义序列开始符 CSI,Control Sequence Introducer
  • 37;44;4;1 代表以; 分隔的文本样式控制符,其中 37 代表文本前景色为白色,44代表背景为蓝色,3代表斜体,1代表加粗
  • m 代表结束控制符序列

比如在终端命令行中执行

echo -e "\e[37;44;3;1mLYL\e[0m"

-e 参数用于启用 echo 命令控制符转码,结尾的 \e[0m 代表重置文本样式。

因为 \e 控制符的16进制码为0x1B , 8 进制码为 033 ,所以以下表示方式等价:

  • \e[0m
  • \x1b[0m
  • \x1B[0m
  • \033[0m
  • \u001b[0m

常用文本样式控制符

代码作用备注
0重置/正常关闭所有属性。
1粗体或增加强度
2弱化(降低强度)未广泛支持。
3斜体未广泛支持。有时视为反相显示。
4下划线
5缓慢闪烁低于每分钟150次。
6快速闪烁MS-DOS ANSI.SYS;每分钟150以上;未广泛支持。
7反显前景色与背景色交换。
8隐藏未广泛支持。
9划除字符清晰,但标记为删除。未广泛支持。
10主要(默认)字体
11–19替代字体选择替代字体
20尖角体几乎无支持。
21关闭粗体或双下划线关闭粗体未广泛支持;双下划线几乎无支持。
22正常颜色或强度不强不弱。
23非斜体、非尖角体
24关闭下划线去掉单双下划线。
25关闭闪烁
27关闭反显
28关闭隐藏
29关闭划除
30–37设置前景色参见下面的颜色表。
38设置前景色下一个参数是5;n或2;r;g;b,见下。
39默认前景色由具体实现定义(按照标准)。
40–47设置背景色参见下面的颜色表。
48设置背景色下一个参数是5;n或2;r;g;b,见下。
49默认背景色由具体实现定义(按照标准)。
51Framed
52Encircled
53上划线
54Not framed or encircled
55关闭上划线
60表意文字下划线或右边线几乎无支持。
61表意文字双下划线或双右边线
62表意文字上划线或左边线
63表意文字双上划线或双左边线
64表意文字着重标志
65表意文字属性关闭重置60–64的所有效果。
90–97设置明亮的前景色aixterm(非标准)。
100–107设置明亮的背景色aixterm(非标准)。

下图对应上表只有一个颜色代码的情况(颜色编码只支持 3 或 4 位,也就是只有8种或16种)

为什么是8或16种?因为初始的规格只有8种颜色,只给了它们的名字。SGR参数30-37选择前景色,40-47选择背景色。相当多的终端将“粗体”(SGR代码1)实现为更明亮的颜色而不是不同的字体,从而提供了8种额外的前景色,但通常情况下并不能用于背景色

3bit-color

下图对应代码为 38 或者 48 的设置背景的颜色选择(即8位编码,共256种颜色(2^8) )

8bit-color

  • 0-7:标准颜色(同ESC [ 30–37 m)
  • 8-15:高强度颜色(同ESC [ 90–97 m)
  • 16-231(6 × 6 × 6 共 216色): 16 + 36 × r + 6 × g + b (0 ≤ r, g, b ≤ 5)
  • 232-255:从黑到白的24阶灰度色

代码格式如下

\e[ … 38;5;<n> … m    # 选择前景色
\e[ … 48;5;<n> … m    # 选择背景色

随着显卡的更新迭代,某些终端已经支持渲染 24 位色彩。格式如下

\e[ … 38;2;<r>;<g>;<b> … m    # 选择RGB前景色
\e[ … 48;2;<r>;<g>;<b> … m    # 选择RGB背景色

上面的字体样式控制可以混合使用,下面同时设置前景和背景色

本篇着重说明 ANSI color,其他终端控制输入输出等内容不再研究。

实际应用

在开发web端的日志组件或Web页面上的命令行终端时,知道 ANSI 转义码会让工作更加轻松。因为这可能会避免你对着一堆的乱码发呆。当然还可以使用一些第三方库将 ANSI color 转译成 html 输出,这样操作起来会更加方便。例如 github.com/drudru/ansi…

参考