SGR 冒号子参数 — ITU-T T.416 替代写法(38:2:: / 48:2:: / 38:5:)
在扩展颜色子参数之间使用 :(0x3a)代替 ;(0x3b)—— 规范认可的写法,可消除复合 SGR 与独立 SGR 的歧义。
字节形式
涵盖所有常见的字符串字面量写法,方便正反查找。
\x1b[38:2::255:128:64m (T.416) \x1b[38;2;255;128;64m (xterm-legacy)\033[38:2::R:G:Bm\e[38:2::R:G:BmESC [ 38 : 2 :: R : G : B m1b 5b 33 38 3a 32 3a 3a ... 6d说明
ITU-T 建议书 T.416 / ISO/IEC 8613-6(1993)—— SGR 子参数的冒号分隔写法。xterm 最初引入扩展颜色时全程使用分号(\x1b[38;2;R;G;Bm),而正式标准保留 :(0x3a)作为子参数分隔符(同一个 SGR 参数内部),;(0x3b)作为参数分隔符(独立 SGR 代码之间)。形式如下:
- 24 位真彩色:\x1b[38:2::R:G:Bm(前景)/ \x1b[48:2::R:G:Bm(背景)。2 后的空槽(构成 ::)是可选的色彩空间 ID —— 空表示 RGB,但 T.416 允许 38:2:Pcs:R:G:B,其中 Pcs 标识 CIE Lab / CIE u'v'L' 等。多数模拟器忽略 Pcs,把该槽当装饰。
- 256 色:\x1b[38:5:Nm / \x1b[48:5:Nm。注意:5 与 N 之间只有一个冒号 —— 没有 :: 空槽,因为 256 色形式没有色彩空间参数。
- CMY(38:3:Pcs:C:M:Y)和 CMYK(38:4:Pcs:C:M:Y:K)变体在 T.416 中存在但基本无人实现。
为何重要:xterm 原始形式 \x1b[38;2;R;G;Bm 对严格遵循 SGR 的解析器有歧义。每个分号分隔的 token 本应是独立的 SGR 代码,严格解析器把 38;2;R;G;B 看成五个独立代码:38(把前景设为下一项)、2(可能解为「淡显」!)、然后 R G B 又作为 SGR 代码。冒号形式 38:2::R:G:B 无歧义,因为整个复合是一个单参数含子 token —— 冒号清晰地嵌套在 38 之下。一致性现状:
- 支持冒号形式:kitty(0.17 起)、foot、WezTerm、alacritty(0.10 起)、ghostty、iTerm2、mlterm、konsole 22.04+、xterm 273+、最新 gnome-terminal。
- 仅支持分号形式:极老的模拟器、较旧的 Windows ConPTY、部分嵌入式 VT 克隆。
- 两者皆支持:上一列表中所有现代模拟器 —— 它们在真彩色 / 256 色槽中将 ; 与 : 视为等价以免破坏既有软件。
T.416 还为 SGR 4 下划线样式定义了冒号子参数 —— \x1b[4:0m(无)、\x1b[4:1m(单线,同 4m)、\x1b[4:2m(双线)、\x1b[4:3m(卷曲 / 波浪)、\x1b[4:4m(点状)、\x1b[4:5m(虚线)—— 以及下划线颜色对 \x1b[58:2::R:G:Bm(下划线颜色设为 RGB)/ \x1b[59m(恢复默认下划线颜色)。波浪下划线是这里的杀手特性 —— 终端层的 IDE 风「拼写错误」视觉。
面向可移植软件:安全模式是发分号形式(每个模拟器都还认得),但在消费任意日志文件的 ANSI 字节时两种形式都解析。
规范出处: ITU-T Rec. T.416 (ISO/IEC 8613-6) / xterm-ctlseqs (SGR Pm)
参数
| Pcs | 在 2 / 3 / 4 模式字节之后的可选色彩空间 ID。为空(构成 ::)表示在默认色彩空间下的 RGB / CMY / CMYK。多数模拟器忽略。 |
| underline-style | 在 4: 之后 —— 0 无、1 单线、2 双线、3 卷曲、4 点状、5 虚线。卷曲(3)即 IDE 风波浪下划线。 |
示例
# Strict T.416 truecolor (note the `::`):\nprintf '\033[38:2::255:128:64morange text\033[0m\n'\n# Curly underline for spell-check overlays:\nprintf '\033[4:3mtypo\033[0m\n'import sys\nRGB = (255, 128, 64)\nsys.stdout.write(f'\x1b[38:2::{RGB[0]}:{RGB[1]}:{RGB[2]}morange\x1b[0m\n')\n# Underline colour (T.416 58 / 59):\nsys.stdout.write('\x1b[4m\x1b[58:2::255:0:0merror\x1b[59m\x1b[24m\n')// Emit semicolon form (most portable) but parse both:\nfmt.Print("\x1b[38;2;255;128;64morange\x1b[0m\n")\n// T.416 strict form:\nfmt.Print("\x1b[38:2::255:128:64morange\x1b[0m\n")// Curly underline + RGB underline colour:\nprocess.stdout.write('\x1b[4:3m\x1b[58:2::200:80:80mmisspelled\x1b[59m\x1b[24m\n')/* T.416 256-color: single colon, no empty slot: */\nprintf("\x1b[38:5:208morange-216\x1b[0m\n");\n/* Truecolor with empty colorspace slot: */\nprintf("\x1b[48:2::20:20:60mdeep blue bg\x1b[0m\n");终端支持
- xterm
- 支持
- Linux console (fbcon)
- 不支持
- macOS Terminal.app
- 不支持
- iTerm2
- 支持
- Windows Terminal
- 部分
- cmd.exe / ConPTY
- 不支持
- kitty
- 支持
- alacritty
- 支持
- WezTerm
- 支持
- Ghostty
- 支持
- GNOME Terminal
- 支持
- Konsole
- 支持
- tmux
- 部分
- GNU screen
- 不支持
| xterm | Linux console (fbcon) | macOS Terminal.app | iTerm2 | Windows Terminal | cmd.exe / ConPTY | kitty | alacritty | WezTerm | Ghostty | GNOME Terminal | Konsole | tmux | GNU screen |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 支持 | 不支持 | 不支持 | 支持 | 部分 | 不支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 部分 | 不支持 |