跳到主要内容
ansicode

CHA — 光标水平绝对位置(列)

将光标移动到当前行的第 N 列(从 1 开始)。

字节形式

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

\\x1b[\x1b[NG
\\033[\033[1G
\\e[\e[1G
ESC [ESC [ N G
hex1b 5b <N> 47

说明

ECMA-48 §8.3.9 —— Cursor Horizontal Absolute(光标水平绝对位置,CHA)。末字节 G,字节序列 \x1b[<N>G,N 为基于 1 的列。仅设置列,不影响行;N 省略时默认为 1(\x1b[G = 「移到第 1 列」)。VPA(\x1b[<N>d,垂直位置绝对)的水平对照,也是 CUP(\x1b[<r>;<c>H,完整行+列)的「列半边」。最常用的写法是 \x1b[1G\x1b[K(跳到第 1 列 + 擦到行尾)—— 在 CRLF 终端上视觉等价于 \r\x1b[K,但完全没有换行语义;当写入端位于 DECSTBM 滚动区域内或处于 noecho 原始模式 TTY 上(\r 可能被意外解释)时,这一点尤为关键。

可移植性 —— 通用。xterm、iTerm2、kitty、alacritty、wezterm、gnome-terminal、Konsole、Ghostty、Windows Terminal、ConPTY 1809+、Linux console 全部支持 CHA。HPA(\x1b[<N>\,末字节 0x60 反引号)是 ECMA-48 §8.3.57 的同义形式,语义完全一致 —— 接受其一的终端必然接受另一个。超界列值钳制到最右可视列(或启用 DECSLRM 时为左/右边距区域的最右列,需模拟器支持边距)。普遍的绊脚石是 1 基与 0 基索引:第 1 列才是最左,而非第 0 列。xterm 及多数现代模拟器把 \x1b[0G 当作 \x1b[1G —— 因为参数 0` 被解释为「使用默认」,CHA 的默认即 1 —— 但依赖此行为脆弱,规范正确的最左列值是 1。tmux 原样转发。

无「关闭」—— CHA 是无状态移动,不是切换。重绘惯用法为 \x1b[1G\x1b[K<文本>;原地旋转图标与进度条则用 \x1b[<col>G 定位到已知列后再写入。当 \r 可能被过滤(熟模式 TTY 将 \r 翻译为 CRLF,或 TUI 独立追踪列位、不依赖终端自身的 CR 处理)、或希望该移动对不特殊处理 \r 的解析器可见时,CHA 优于 \r。绝对定位且行号同样关键时,CUP(cursor-position\x1b[r;cH)比 CHA + VPA 少一次往返。相关:cursor-position(CUP —— 单次移动到绝对行+列)、cursor-next-prev-line(CNL / CPL —— 垂直移动且强制列归 1)、erase-line(EL —— 部分/整行擦除,重绘循环的天然配对)。

规范出处: ECMA-48 §8.3.9 (CHA)

示例

bash
printf 'progress:\033[20G50%%\033[1G' 
python
print('\x1b[20G50%')
go
fmt.Print("\x1b[20G50%")
javascript
process.stdout.write('\x1b[20G50%')
c
printf("\x1b[20G50%%");

在哪里用到

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

  • tqdm, pip, npm download progress bars速率 / ETA / 百分比通过 `\x1b[<col>G` 定位到固定列,无论文件名长度如何布局都保持对齐
  • starship, oh-my-zsh, powerlevel10k right-prompts右对齐段落计算 `COLUMNS - len(content)` 后发 CHA 跳到该列再写入
  • git rebase --interactive editor screens用 CHA + EL 组合原地重绘高亮的提交行,不打扰周围上下文
  • whiptail, dialog (TUI form widgets)每个表单字段通过 CHA 把标签与输入框放到预定列
  • fzf — search-result preview pane positions matched highlights via CHA before underlining the substring

常见问题

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

为什么 \x1b[0G 落在第 1 列而非第 0 列?
因为 CHA 是 1 基的 —— 第 1 列才是最左格,根本没有第 0 列。ECMA-48 §5.4 规定 SGR / 光标定位参数值为 0 表示「使用默认」,而 CHA 的默认即 1。所以 \x1b[0G\x1b[1G\x1b[G(省略)都落到最左列。规范写法是 \x1b[1G;依赖 01 隐式归一在 xterm 和所有主流模拟器上能跑,但属未定义行为,会被严格解析器(部分 ECMA-48 一致性测试套件)标记。
什么时候该用 \x1b[1G 而不是 \r 来回到第 1 列?
三种场景。(1)原始模式 TTYOPOST / onlcr 已关——\r 不再具有行规程会篡改的特殊含义(其实它也会被原样透传,但能避开自定义 termios 标志造成的意外交互)。(2)位于 DECSTBM 滚动区域内,需要回到 *当前行* 第 1 列且不冒触发隐式滚动的风险 —— CHA 是纯列移动,\r\n 是两次操作而 \n 部分可能滚屏。(3)下游解析器(录制器、转义感知 linter、转义感知分页器)不特殊处理 \r 时——发 CHA 让意图作为 CSI 序列显式表达。普通 cooked 模式 shell 输出用 \r 即可,且字节更短;只在以上三类场景需要时改用 \x1b[1G

终端支持

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

相关序列

在家族食谱中

CSI 食谱 · 2. 光标移动 —— CUU / CUD / CUF / CUB + CUP + CHA / VPA