跳到主要内容
ansicode

CUP — 设置光标位置

将光标移动到绝对行/列(从 1 开始)。

字节形式

涵盖所有常见的字符串字面量写法,方便正反查找。

\\x1b[\x1b[row;colH
\\033[\033[1;1H
\\e[\e[1;1H
ESC [ESC [ row ; col H
hex1b 5b ... 48

说明

Cursor Position(光标定位)。\x1b[row;colH 将光标移到给定的绝对行 / 列。末字节 H(CUP)与 f(HVP,Horizontal and Vertical Position)互为同义 —— 行为等价、参数形态相同,在上面支持矩阵中的每个终端上字节级可互换。行列从 1 开始计数(不是 0 —— VT100 / ECMA-48 历史沿革)。同时省略两个参数时默认为 (1,1),即屏幕左上角,或者 —— 当 DECOM(原点模式)启用时 —— 当前 DECSTBM 滚动区域的左上角。超出范围的值会被钳制到可视区域:\x1b[9999;9999H 落到右下角,而不是屏外某处。ECMA-48 §8.3.21 规定参数语义;xterm-ctlseqs 文档化了 DECOM / DECSTBM 交互。

首要移植性陷阱是默认参数陷阱。CSI 默认参数并非统一为 0 —— \x1b[H 默认 (1,1)(回家);\x1b[;5H 行默认 1(第 1 行第 5 列);\x1b[5H 是第 5 行第 1 列(只给第一个参数)。依赖「CSI 默认 0」的程序会静默破坏布局 —— 值有意义时务必显式写参数(每条指令的默认值表见 csi-default-params)。另一个活跃陷阱是 DECOM / DECSTBM 坐标系迁移:若 TUI 之前用 DECSTBM(\x1b[t;b r)设了滚动区域,又用 DECOM(\x1b[?6h)开了原点模式,\x1b[1;1H 现在会落到*区域*顶部而非绝对屏顶 —— 你以为「应该出现在第 1 行」的调试日志会静默漂到屏中。处理办法:自行跟踪原点模式状态,或在绝对定位前无条件先发 \x1b[?6l 关掉原点模式。现代终端覆盖一致:xterm、iTerm2、kitty、alacritty、wezterm、ghostty、Windows Terminal、conhost.exe / ConPTY(Win10 1709+)、Linux console、macOS Terminal.app —— 全部支持完整 CUP / HVP,无怪癖。

CUP 是绝对移动 —— 没有「撤销」参数。要在临时移动后回到原光标位置,先用 DECSC(\x1b7)保存,再用 DECRC(\x1b8)恢复 —— 见 cursor-save-restore。需要相对运动(上 / 下 / 左 / 右移动 N 格),用 CUU / CUD / CUF / CUB(见 cursor-move)。HVP 别名 \x1b[r;cf 单独文档化在 csi-hvp,接受完全相同的参数 —— 代码库内挑一种形式并保持一致。定位之后常见的后续操作:EL \x1b[K 清掉目的行(见 erase-line);EL 加上 SGR 在已知位置画带标签的状态行。

规范出处: ECMA-48 §8.3.21 (CUP)

示例

bash
printf '\033[2;5HHello at (2,5)\n'
python
print('\x1b[2;5HHello at (2,5)')
go
fmt.Print("\x1b[2;5HHello at (2,5)\n")
javascript
process.stdout.write('\x1b[2;5HHello at (2,5)\n')
c
printf("\x1b[2;5HHello at (2,5)\n");

在哪里用到

实际会发出该序列的工具——把抽象字节锚定到你已经用过的命令上。

  • htop, top, btop每个刷新周期原位重绘逐行统计网格
  • vim, neovim status line redraw
  • tmux pane redraws
  • less — re-positioning on scroll

常见问题

针对这条序列,开发者真正会去搜索的问题的简短回答。

行号和列号是 0 起还是 1 起?
1 起。\x1b[1;1H 是左上角;\x1b[H(无参数)默认值也是 \x1b[1;1H。ECMA-48 / VT100 不存在第 0 行 / 第 0 列——这是从打字机的 1 起纸张位置继承下来的。\x1b[0;0H 是未定义行为,多数终端会夹到 (1,1)。
如果光标超出屏幕——比如 \x1b[9999;9999H——会怎样?
所有合规终端都会夹到可见区域:光标落到右下角而不是屏幕外。这是「跳到最后一行」的常用技巧——配合 \x1b[K 可以擦掉最后一行作为状态条。开启了 DECSTBM 滚动区域时,夹到区域边界而非整屏边界。
\x1b[H(CUP)与 \x1b[f(HVP)是同一个吗?
实际上是。CUP(Cursor Position,结束字节 H)与 HVP(Horizontal and Vertical Position,结束字节 f)参数完全相同,所有终端的行为也按字节一致。这是历史分裂——VT100 同时提供了两者。代码库挑一种用即可;实战中 H 远更常见。

终端支持

xterm
支持
Linux console (fbcon)
支持
macOS Terminal.app
支持
iTerm2
支持
Windows Terminal
支持
cmd.exe / ConPTY
支持
kitty
支持
alacritty
支持
WezTerm
支持
Ghostty
支持
GNOME Terminal
支持
Konsole
支持
tmux
支持
GNU screen
支持

相关序列

在家族食谱中

CSI 食谱 · 1. 信封 —— `\x1b[` …… `<结尾字节>`