ANSI转义序列

208 阅读7分钟

文章首发于个人博客

起因

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

ANSI转义序列

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

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)
	}
}

语法

整体的语法为:

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
fH(光标定位)\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转义序列的颜色部分类似。