利用Linux控制终端代码实现特殊显示
利用Linux控制终端代码实现特殊显示
其实之前就知道类似"\033[32m
"这样的字符串可以打印出绿色字体,以便在输出中标记有特殊含义的字符串;
但是对这个原理其实一直不甚明了;
但是通过查阅了一些资料以后,算是对这个东西有一点了解了;
首先\033
这个写法并不是最简洁的写法,最简单好记的写法是\e
,这实际上是ASCII码中ESC字符的转义写法;
ASCII码中ESC为27号字符,八进制为33(O),C语言中用0开头的整数表示八进制数字,因此\033
就是表示这是个ESC字符;
后面的[
则是一个固定要求,需要将ESC
与[
组合起来成为ESC [
,表示控制图像释义(Set Graphics Rendition,SGR abbr.)序列,
在ESC[
后跟有一个数字,这个数字决定了接下来终端打印出的字符的图像特色;
有关颜色的设置
先说颜色设置是因为颜色是最常用的功能,倒不是别的什么逻辑顺序的原因;
有关前景色的设置
前景色设置表格
数字 | 前景色 | 数字 | 前景色 |
---|---|---|---|
30 | 黑色 | 90 | 浅灰色(亮黑色) |
31 | 红色 | 91 | 粉红色(亮红色) |
32 | 绿色 | 92 | 浅绿色(亮绿色) |
33 | 黄色 | 93 | 浅黄色(亮黄色) |
34 | 蓝色 | 94 | 浅蓝色(亮蓝色) |
35 | 紫色 | 95 | 品红色(亮紫色) |
36 | 青色 | 96 | 淡青色(亮青色) |
37 | 白色 | 97 | 荧白色(亮白色) |
大多数网上的资料只提到了30-37这八种前景色设置,其实还有90-97这八种前景色设置,但是9x的前景色相对于3x前景色也仅仅只是选取了更亮的色彩;所以我在表格中用括号标注了9x这些颜色的产生方式;
有关背景色的设置
背景色设置表格
数字 | 背景色 | 数字 | 背景色 |
---|---|---|---|
40 | 黑色 | 100 | 深灰色 |
41 | 红色 | 101 | 浅红色 |
42 | 绿色 | 102 | 浅绿色 |
43 | 黄色 | 103 | 浅黄色 |
44 | 蓝色 | 104 | 浅蓝色 |
45 | 紫色 | 105 | 品红色 |
46 | 青色 | 106 | 淡青色 |
47 | 灰色 | 107 | 白色 |
背景色的规律和前景色的规律也是一模一样的,10x的背景色是4x背景色的浅色版本
控制功能
目前可以完全解释的功能
控制功能表格
数字 | 功能 | 数字 | 功能 |
---|---|---|---|
0 | 所有属性设置为默认值 | ||
1 | 设置加粗 | 21 | 关闭加粗 |
2 | 设置不明显 | 22 | 关闭不明显 |
4 | 设置下划线 | 24 | 关闭下划线 |
7 | 设置反色 | 27 | 关闭反色 |
这些是由于现象不明显,所以推测的功能表格
数字 | 功能 | 数字 | 功能 |
---|---|---|---|
5 | 设置闪烁 | 25 | 关闭闪烁 |
还没有搞清楚,但存在于手册中的功能
还有一些功能是存在的,但是我无法理解这些功能,这些功能的文字介绍可以通过manpages的console_codes(4) — Linux manual page查找到
这些功能中,我只测试了一部分,其他介绍来自Linux Manual Page中文版本,控制终端代码的调出命令为man -L zh-CN console_codes
有关中文版Linux Manual Page请参阅man pages zh,本文涉及到的部分是man4 console_codes
个人尚未测试的数字表格(引用自man-pages-zh(2021年2月17日版本))
数字 | 功能 |
---|---|
10 | 重设选定映像,显示控制标记,反转元素标记. |
12 | 选择空映像,设置显示控制标记,重设反转标记.(在完成映像表转换之前反转标记引起每一字节的高位反转.) |
21 | 设置正常亮度(和ECMA-48不兼容) |
22 | 设置正常亮度 |
38 | 打开下划线,设置默认前景色 |
39 | 关闭下划线,设置默认前景色 |
49 | 设置默认背景色 |
测试结果
测试结果如图:
测试代码我稍后应该会上传到我的github仓库中
未完的想法
另外我似乎发现了一些规律,
前景色是3x和9x,背景色是4x和10x,其中3x到4x距离为10,9x到10x距离也为10,不过这个现象很明显就是了,
主要是很多功能的开关在x和2x成对地出现,同时缺失了3、6处的功能介绍,而且这些数字是如此地分散,像是刻意互相避开了什么容易交叉的部分;
我不禁怀疑这些所谓的控制字其实只是在控制一个类似二进制串的东西,二进制串上的每一位的0或1是某种开关,而这个二进制串一起决定了字符的图像样式;
0的二进制是0,作为默认也没有什么可想的
1的二进制是0000,0001,21的二进制是0001,0101
2的二进制是0000,0010,22的二进制是0001,0110
4的二进制是0000,0100,24的二进制是0001,1000
这显然不像上述猜测中的简单的二进制开关,这中间应该有更加复杂的运算规则,像是与、或、同或、异或之类的运算之后,才写入最终结果
我可能需要一张足够大的输入输出表才能看出其中的规律
同时,manpages中提到了ECMA-48,这似乎是一个标准,也值得去查一下;
按说发现了这个线头,应该继续探究下去的,
但是夜太深了,以后再说吧
Knighthana
2021年2月17日
SGR\e[38;a;b...m
对于终端字符串色彩的控制
上文中提到,30-37是8种前景色,并且提到38
的作用不完全符合介绍,用途不明,
事实上并非如此,那些介绍适用于小于 Linux 3.16 版本的内核,并不适于现在广泛应用中的5.x与6.x内核
根据最新 1
man console_codes
Commands 38 and 48 require further arguments:
;5;x
256 color: values 0..15 are IBGR (black, red, green, ... white),
16..231 a 6x6x6 color cube, 232..255 a grayscale ramp
;2;r;g;b
24-bit color, r/g/b components are in the range 0..255
38
的含义是“设定前景色”,但它不能单独使用,还需要之后用分号分割的数个数字来辅助确定颜色,同样地,48
表示“设定背景色”
可以用5
表示使用256色模式,256色调色板对应的数字可以通过"xterm 256 color code"一类的关键词搜索到
例如这个参考 256 Colors Cheat Sheet
\e[38;5;208
可以得到一个非常不错的橙色
还可以通过使用2
来使用R;G;B方式,这可以获得256×256×256的颜色选择空间
Knighthana
2023年11月17日