0%

终端的特殊控制符

之前碰到过很多终端工具可以显示非常好看的进度条,或者显示丰富的颜色,甚至还有的直接可以在终端通过字符绘制UI(a.k.a. TUI),我一直都很好奇是怎么做到的。之后又知道了curses这个Python库和它的一些高层封装(例如asciimatics),然后最终在Stack Overflow里面查到了这些都是通过特殊的终端控制符来实现的。本文就介绍这些终端控制符的使用方法,他们很适合用来写一个简单无依赖的TUI。如果需要更复杂和全面的TUI功能,还是最好使用封装好的库。

ASCII 控制符

在最开始接触编程的时候,如果你学的是C,那你一定很熟悉\n,这就是一个”换行“的转义字符,代表终端光标令起一行。有时你还会碰到\r,这是”回车“。“回车”这个名字来源于打字机时代,在使用打字机的时候,如果你需要新起一行,那么需要的操作是:转动滚筒把纸往外抽一行,再把字车(相当与打印机的打印头)移到最左端。这两个操作的名字分别是“换行”和“回车”。因此严格来说另起一行的字符串应该是\r\n,这也是Windows的标准,而在Unix中则简化成\n会自动执行回车。

换行和回车是两个非常常用的控制字符,也是定义在了ASCII表中的控制字符。在ASCII表中还定义了其他的控制字符,列在下面了。

ASCII名字ASCII码printf风格转义用途
BEL 铃声0x07\a哔一下(执不执行取决于终端)
BS 退格0x08\b*光标回退一格
ESC 退出0x1B\e可代表按下ESC键,不是C标准
FF 换页0x0C\f光标移到新一页
LF 换行0x0A\n光标下移一行
CR 回车0x0D\r光标回到行首
HT 水平制表0x09\t标记水平制表位(Tab键)
VT 垂直制表0x0B\v标记垂直制表位
NUL 空值0x00\0代表啥也没有,C里面终结字符串
--**\c终止输出,基本不被支持了

*光标这里泛指各类终端的指示当前文本位置的东西,在打字机上叫“type guide”,在显示屏上里面叫“光标 cursor”,而在有些场合也叫指针。
**这个用法貌似只在一些终端中有,我也不确定它是否有对应一个字符。在GNU的文档里有简短解释。

ANSI/VT100 控制符(串)

很多终端都支持彩色文字的输出,而彩色文字的表达方式通常都参考ANSI的色彩标准。而ANSI用来实现色彩显示的转义表还定义了指针控制和设备管理的功能。

这一类控制符实际上是个字符串,所以应该叫控制串?他们都由<ESC>字符开头,也就是0x1B。所以我推测实际上ESC的双关(退出/转义)也被用到了这里哈哈。以下内容大部分来自 ANSI/VT100 Terminal Control Escape Sequences 表格,详细解释可以参考这个表格以及维基的页面。链接都放在引用部分。

0x1B在一些终端中会用^[代表,因此如果你看到了^[[那通常也都是通过这种方法转义的字符序列。

我把这个表中能用于bash的字符都拎出来放在下面了。以下表中的转义序列名称都是我自己翻译的,我不知道有没有统一的中文翻译hhh。

终端设备相关

名称转义字符串
查询设备码<ESC>[c
报告设备码<ESC>[{code}0c
查询光标位置<ESC>[6n
报告光标位置<ESC>[{ROW};{COLUMN}R
重置设备<ESC>c

可以在你的终端里输入printf "\x1b[c",看看会输出什么

光标控制

名称转义字符串
设置指针位置<ESC>[{ROW};{COLUMN}H
指针上移<ESC>[{COUNT}A
指针下移<ESC>[{COUNT}B
指针前移(右移)<ESC>[{COUNT}C
指针后移(左移)<ESC>[{COUNT}D
保存指针位置<ESC>[s
复原指针位置(到保存位置)<ESC>[u
保存指针位置和属性<ESC>7
复原指针位置和属性<ESC>8

滚动

名称转义字符串
启用滚动<ESC>[r
启用指定行之间滚动<ESC>[{START};{END}r
向下滚动一行<ESC>D
向上滚动一行<ESC>M

制表

名称转义字符串
设置对齐位<ESC>H
清楚对齐位<ESC>[g
清楚所有对齐位<ESC>[3g

清除

名称转义字符串
清除文字到行末<ESC>[K
清除文字到行首<ESC>[1K
清除整行<ESC>[2K
清除文字到屏幕底<ESC>[J
清除文字到屏幕顶<ESC>[1J
清屏<ESC>[2J

定义

  • 设置文字绑定: <ESC>[{key};"{string}"p

显示颜色属性

  • 设置光标属性: <ESC>[{attr1};...;{attrn}m
属性代码属性效果属性代码属性效果属性代码属性效果
0重置30前景黑40背景黑
131前景红41背景红
232前景绿42背景绿
4下划线33前景黄43背景黄
5闪烁34前景蓝44背景蓝
7反向35前景紫45背景紫
8隐藏36前景青46背景青
37前景白47背景白

Reference

ASCII转义符

ANSI转移符

Treat me some coffee XD