ESC 转义码 —— 独立的两字节序列
独立 escape 序列。`ESC X` 家族(其中 `X` 是 `0x20–0x7e` 内的单字节),不属于 CSI / OSC 框架 —— `ESC c`(完整重置 / RIS)、`ESC 7` / `ESC 8`(DECSC / DECRC 光标保存与恢复)、小键盘模式切换、字符集指派。比 CSI 语法更古老,部分早于 ECMA-48。
8 条序列
ESC 食谱 —— 六步把裸转义家族读透
在 CSI 出现之前,先有 ESC X —— \x1b 后跟一个单字节就足以自成语义。这一支多数比 ECMA-48 早十年,仍然活到 2026 是因为 xterm 把每一条 VT100 祖先都照顾到了。下面六步覆盖你今天依旧会发的几道:硬复位与软复位的差别、制表位、键盘小键盘模式、VT100 双宽 / 双高横幅族、通往 8 位 C1 的锁定切换桥,以及现代协议(Kitty 图形等)借道的 APC 信封。
1. 硬复位 vs. 软复位 ——
\x1bc(RIS)与\x1b[!p(DECSTR)两种「让终端回到初始」的口味。
\x1bc是 RIS(Reset to Initial State)—— 核选项。它清主屏 + 备用屏、把每个支持回滚的终端的滚动缓冲也丢了、重置所有 SGR + DEC 私有模式 + 光标样式、恢复 wraparound + 自动重复、复原默认字符集、并把光标拉回原点。TUI 崩了、用户的 prompt 变成五彩乱码时就发它。\x1b[!p是 DECSTR(软复位)—— 同样意图、更小副作用。DECSTR 不动屏内容、不动滚动缓冲、不动备用屏指针;它只重置模式位、SGR、边距、光标形状与 Origin Mode。长时运行的 TUI 想清理状态又不愿黑屏一下时就用 DECSTR。配套页decstr-side-effects列举了二者各自动了哪些模式 —— 在你押注某一位会幸存之前请先查那张表。2. 制表位 ——
\x1bH(HTS)设、\x1b[g(TBC)清默认终端每 8 列一个制表位 ——
\t(\x09,HT)跳到下一个。要改这个网格,把光标移到第 N 列,发\x1bH(HTS),那一列即变成制表位、直到另行通知。清掉:\x1b[g清当前列的位,\x1b[3g清整行所有位。这对组合让你不用手动补空格就能做出真正的列对齐输出 ——column(1)类工具和 TUI 状态栏(右边缘要对齐而左侧长度不定)都用得上。Linux 2.6 之前 console 也认,但粒度只到 8 列;今天所有现代模拟器(xterm、kitty、wezterm、iTerm2、Windows Terminal、ghostty、alacritty)都是单列粒度。tput hts/tput tbc是 terminfo 封装;stty tab0把所有位清零,shell 就会收到原始\t字节。3. 小键盘模式 ——
\x1b=/\x1b>(DECKPAM / DECKPNM)数字小键盘有两副面孔。默认(DECKPNM,
\x1b>)是**数字模式** —— 按7发字节7、按+发+。发\x1b=(DECKPAM,应用模式)之后,同一组物理键改发 SS3 前缀的转义:\eOq表示1、\eOr表示2、\eOM表示 Enter、\eOk表示+。这就是vim、less、readline、tmux以及几乎所有全屏 TUI 启动时都开应用模式的原因(terminfo 的smkx能力,rmkx回退)—— 它们要给每个小键盘键一个独立的字节签名,才能把<kp-Enter>与<Enter>分开绑定。若 TUI 异常退出后你的+在 prompt 上变成了Ok,就是卡在应用模式 ——printf '\033>'(DECKPNM)就能恢复。更广的输入面参考/keymap。5. 锁定切换与 8 位 C1 桥 ——
\x1bn/\x1bo/\x1b|与\x80-\x9F在 UTF-8 接管之前,终端要管四个字符集槽(G0 / G1 / G2 / G3)并通过锁定切换决定哪个充当 GL / GR 半:
\x1bn(LS2)把 G2 设为 GL 半直到另行通知、\x1bo(LS3)选 G3,\x1b|/\x1b}/\x1b~是 GR 半锁定形(LS3R / LS2R / LS1R)。用\x1b( / ) / * / +加一个终结字节(B= ASCII、0= DEC 特殊图形、A= 英国等)把字符集塞进槽位。历史伙伴是 8 位 C1 行\x80-\x9F:每个两字节ESC X引导符(\x1b[CSI、\x1b]OSC、\x1bPDCS、\x1b\\ST、\x1bNSS2、\x1bOSS3)都有一个单字节 8 位别名(\x9b、\x9d、\x90、\x9c、\x8e、\x8f)。UTF-8 locale 下 0x80-0xBF 全是续字节,发原始 C1 会把字节流弄花 —— 现代模拟器在LANG=C.UTF-8下大多静默丢弃。**始终发 7 位\x1bX形**;8 位形是只读的遗物,仅会在老 VT 手册与 CTF 题里碰见。6. APC —— 现代应用对应用信封
\x1b_ …… \x1b\\APC(应用程序命令)是 ECMA-48 中与 DCS / OSC 同辈、专为**应用对应用**消息保留的引导符 —— 终端应当把主体不透明地搬运给同 TTY 上监听的对端、自身不解释。信封是
\x1b_<body>\x1b\\(8 位形\x9f<body>\x9c),与 DCS / OSC 共享 ST 家族。原始「在瘦客户机与宿主应用之间打隧道」的用例已死,但字节形状被现代协议**重新殖民**:**Kitty 图形协议**是头号用户 ——\x1b_G<key>=<val>,…;<base64-像素>\x1b\\(Kitty、Konsole、WezTerm、Ghostty 都实现;slugdcs-kitty-graphics名字误导 —— 实际字节族是 APC)。**VS Code shell 集成**用\x1b_633;…\x1b\\承载它不愿用 OSC 133 公开的标记。**Windows Terminal** 在预览版里试用\x1b_<JSON>\x1b\\。把 APC 视为「要么抵达认识首字节标签的对端、要么完全消失」—— 永远不要把它当作保证可见的通道。要注意的解析 Bug:实现了 OSC + DCS 却忘了 APC 分派的终端,会把_G…**直接打到屏幕**而非吞掉 —— 那一串散落的_G字面就是 Kitty 图形渲染坏掉的招牌征。
本家族的全部序列
- RIS — 重置到初始状态(终端硬重置)
\x1bc终端硬重置:清屏 + 清回滚、重置所有模式与 SGR、光标回到原点。
- HTS — 水平制表位设置(ESC H)
\x1bH在当前光标列设置一个 tab 停位 —— 与 TBC 互为伙伴。
- C1 控制字符 —— ESC 序列的 8 位单字节等价形式(0x80–0x9F)
\x9b CSI \x9d OSC \x9c ST \x90 DCS \x85 NEL \x88 HTS \x84 IND \x8d RI8 位 C1 控制字节(0x80..0x9F)—— CSI、OSC、ST、DCS、NEL、HTS、IND、RI —— 及其 7 位 ESC <letter> 等价形式。
- DECKPAM / DECKPNM — 小键盘应用 / 数字模式(ESC = / ESC >)
\x1b= (DECKPAM) \x1b> (DECKPNM)在数字小键盘发送应用转义序列(\eOM / \eOj …)与发送 ASCII 数字之间切换 —— vim / less / readline 小键盘行为的基础。
- DECDHL / DECDWL / DECSWL — 双倍高 / 双倍宽行(ESC # 3 / # 4 / # 5 / # 6)
\x1b#3 (DHL top) \x1b#4 (DHL bottom) \x1b#5 (DECSWL) \x1b#6 (DECDWL)把当前行标记为双倍高(上半 / 下半)或双倍宽 / 单倍高 —— DEC 的逐行大横幅原语,VT100 启动画面常用。
- DECALN — 屏幕对齐测试图案(ESC # 8)
\x1b#8用大写 `E` 字形填满整屏 —— DEC 的 CRT 对齐测试,验证「页面缓冲是否正确接通」的标准烟囱测试。
- 单次切换 / 锁定切换族 —— SS2 / SS3 / LS2 / LS3 / LS1R / LS2R / LS3R
\x1bN SS2 \x1bO SS3 \x1bn LS2 \x1bo LS3 \x1b~ LS1R \x1b} LS2R \x1b| LS3RISO 2022 字符集切换:单次调用 G2 / G3(SS2 / SS3),或将 GL / GR 锁定到不同 G 集(LS2 / LS3 / LS1R / LS2R / LS3R)。与 `\x1b(` / `\x1b)` / `\x1b*` / `\x1b+` G 集指派配对。
- APC —— 应用程序命令(`ESC _ … ESC \\` / `\x9F … \x9C`)
\x1b_<body>\x1b\\ (7-bit) \x9f<body>\x9c (8-bit C1)ECMA-48 为应用对应用消息保留的字符串引导符。现代用途:Kitty 图形协议、VS Code shell 集成、Windows Terminal API 补丁。与 DCS / OSC / PM / SOS 同辈。