起因

近来,翻看gin源码时,无意间看到了green = "\033[97;42m"这种不明所以的代码,遂充满疑惑和好奇,于是就搜索探究了一番,这才知道这叫ANSI转义序列

ANSI转义序列

简单说,就是一种标准化的终端控制序列,用于设置文本样式、颜色和背景等。先放个代码吧,以免不知所云。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
package main

import "fmt"

func main() {
	for i := 0; i <= 10; i++ {
		fmt.Printf("这是\033[%[1]dm<文本属性>%2[1]d\033[0m\n", i)
	}
	s := []int{30, 31, 32, 33, 34, 35, 36, 37}
	for _, v := range s {
		fmt.Printf("这是\033[%[1]dm<16色标准前景色>%2[1]d\033[0m\t\033[%[2]dm<16色亮前景色>%2[2]d\033[0m\n", v, v+60)
		fmt.Printf("这是\033[%[1]dm<16色标准背景色>%2[1]d\033[0m\t\033[%[2]dm<16色亮背景色>%2[2]d\033[0m\n", v+10, v+70)
	}
	for i := 0; i < 256; i++ {
		fmt.Printf("这是\033[38;5;%[1]dm<256色前景色>%3[1]d\033[0m\t\x1b[48;5;%[1]dm<256色背景色>%3[1]d\033[0m\n", i)
	}
}

语法

整体的语法为:

1
ESC+控制序列
  • ESCESC转义字符,固定为\033(八进制)或\x1b(十六进制),告诉终端后面的内容是控制序列

  • 控制序列:有不同分类,一般为序列内容+命令字符的形式,具体语法后面再细说

支持情况

大多数终端都支持ANSI转义序列,但不包括windows平台默认配置的命令提示符PowerShell(也许通过某些配置后是支持的,未深究)。

虽然大多数终端都支持,但支持的情况也是有差异的,即:

  • 有些终端只支持某一部分的ANSI转义序列,其它则不支持

  • 对于同一ANSI转义序列,不同终端的表现形式可能不同

分类

分类 语法 说明
CSI序列 ESC[+参数序列+命令字符 用于控制光标、颜色、屏幕等
直接控制 ESC+命令字符 用于简单控制
OSC命令 ESC]+命令字符+参数+终止符 用于操作系统控制
私有模式控制 ESC[?+参数序列+命令字符 用于配置终端的独有功能(通常由终端制造商或特定标准扩展)

注意:

  • 参数序列若有多个参数,用;进行分隔

  • 命令字符区分大小写

  • 终止符仅OSC命令有,固定为\007\033\\

CSI序列

该分类应该是最常用的。

命令字符 功能 示例
A 光标上移 \033[5A上移5行
B 光标下移 \033[3B下移3行
C 光标右移 \033[10C右移10列
D 光标左移 \033[2D左移2列
E 光标下移并到行首 \033[1E下移1行到行首
F 光标上移并到行首 \033[1F上移1行到行首
G 光标水平绝对定位 \033[10G移动到第10列
H 光标定位 \033[2;10H第2行第10列
J 擦除屏幕 \033[2J清屏
K 擦除行 \033[K清除到行尾
S 向上滚动 \033[5S上滚5行
T 向下滚动 \033[3T下滚3行
m 图形样式 \033[1;31m红色粗体
n 设备状态报告 \033[6n查询光标位置
s 保存光标位置 \033[s
u 恢复光标位置 \033[u
f H(光标定位) \033[2;10f

其中m即图形样式,应该是用得最多的。

图形样式

语法:\033[参数序列m

参数 效果 说明
0 重置所有属性 下面要介绍的文本属性和颜色的设置,在设置完之后将一直生效,通常需要在末尾加上\033[0m来恢复到默认设置
文本属性
  • 语法:\033[单一参数m
参数 效果 重置参数
1 加粗/高亮 22
2 弱化/暗淡 22
3 斜体 23
4 下划线 24
5 慢闪烁 25
6 快闪烁 26
7 反色 27
8 隐藏 28
9 删除线 29
21 双下划线
53 单上划线
73 上标
74 下标
文本颜色
16色模式
  • 语法:\033[单一参数m
16色颜色 参数 效果 参数 效果
标准黑 30 前景色 40 背景色
标准红 31 前景色 41 背景色
标准绿 32 前景色 42 背景色
标准黄 33 前景色 43 背景色
标准蓝 34 前景色 44 背景色
标准品红 35 前景色 45 背景色
标准青 36 前景色 46 背景色
标准白 37 前景色 47 背景色
亮灰 90 前景色 100 背景色
亮红 91 前景色 101 背景色
亮绿 92 前景色 102 背景色
亮黄 93 前景色 103 背景色
亮蓝 94 前景色 104 背景色
亮品红 95 前景色 105 背景色
亮青 96 前景色 106 背景色
亮白 97 前景色 107 背景色
256色模式
  • 前景色语法:\033[38;5;颜色代码m

  • 背景色语法:\033[48;5;颜色代码m

其中,颜色代码

  • 0~15:标准16色

  • 16~231:6 × 6 × 6的RGB立方(即36×R + 6×G + B + 16,R/G/B∈[0,5],最后的16为偏移)

  • 232~255:24级灰度(232=黑,255=白,即g + 232,g∈[0,23],最后的232为偏移)

24位RGB真彩色

前景色语法:\033[38;2;R;G;Bm(R/G/B∈[0,255])

背景色语法:\033[48;2;R;G;Bm(R/G/B∈[0,255])

直接控制

命令字符 功能 示例
7 保存光标位置 \0337
8 恢复光标位置 \0338
D 向下滚动一行 \033D
M 向上滚动一行 \033M
E 换行并回车 \033E
c 重置终端 \033c完全重置终端

OSC命令

命令字符 功能 示例 说明
0 修改窗口标题 \033]0;My Title\007
1 修改图标名称(少用) \033]1;Icon Name\007
2 同 0(修改标题) \033]2;New Title\007
4 修改调色板颜色 \033]4;1;rgb:FF/00/00\007(红) 使用\033]4;颜色索引;default\007恢复默认
8 创建超链接 \033]8;;https://example.com\033\\点击\033]8;;\033\\ 必须使用\033]8;;\033\\终止
10 修改默认前景色(文本) \033]10;rgb:FF/00/00\007(红色)
11 修改默认背景色 \033]11;rgb:00/00/80\007(深蓝)
12 修改光标颜色 \033]12;rgb:FF/FF/00\007(黄色)
? 查询状态 \033]10;?\007查询前景色

总结

ANSI转义序列可以让终端的输出变得更漂亮,更像GUI,而且只是针对终端的一个标准,任何可编写终端应用的语言都可以使用。

想当初刚学完c作为练手写的终端小游戏汉诺塔,若是当时掌握了这个知识点,展示效果绝对要上一个档次。

虽然ANSI转义序列很酷,但写起来还是太啰嗦了,而且代码看起来也更乱,但果然还是封装一下再用会比较舒服,比如:fatih/color就是一个跨平台兼容性更好的设置终端颜色的库,与ANSI转义序列的颜色部分类似。