SU / SD — 向上 / 向下滚动
将屏幕内容向上(SU)或向下(SD)滚动 N 行,光标位置不变。
字节形式
涵盖所有常见的字符串字面量写法,方便正反查找。
\x1b[NS (scroll up) \x1b[NT (scroll down)\033[1S / \033[1T\e[1S / \e[1TESC [ N S / T1b 5b <N> 53 / 54说明
ECMA-48 §8.3.147(SU)与 §8.3.113(SD)。末字节 S = SU(Scroll Up)、T = SD(Scroll Down)。字节序列分别为 \x1b[<N>S 与 \x1b[<N>T;N 省略时默认 1。两者把 *滚动区域内* 内容按 N 行平移,并以空行填补暴露出的行 —— SU \x1b[<N>S 让顶部 N 行消失、底部出现 N 行空白(与新文本自动滚屏方向相反),SD \x1b[<N>T 反之。关键细节:光标位置不变。与 CUU / CUD(cursor-move)正相反 —— 后者只移动光标不影响内容,SU / SD 只移动 *内容* 不动光标,是内容滚动原语,不是光标移动。若已通过 DECSTBM(\x1b[<top>;<bot>r,见 decstbm)限定滚动区域,则只滚动该区域内行;区域外的行原样冻结 —— 正是 TUI 把状态栏钉在原处、让日志视口滚动的依据。
可移植性 —— 在现代模拟器(xterm、iTerm2、kitty、alacritty、wezterm、gnome-terminal、Konsole、Ghostty、Windows Terminal、ConPTY 1809+、Linux console)上通用。最大解析陷阱是末字节 T 也被 xterm 鼠标追踪协议使用(CSI Pe ; Px ; Py ; Pv ; Ph T 高亮追踪,见 xterm-ctlseqs DECSET ?1001)。现代终端按参数个数消歧 —— 单参数 T 是 SD、多参数 T 是鼠标追踪 —— 但要从野外吞入未知 CSI 序列的解析器需同时处理两种形态。部分遗留模拟器实现了 SU 却未实现 SD;若 SD \x1b[T 在目标终端上视觉无效,回退是在区域顶部用 IL(\x1b[<N>L,见 csi-il)插入空行。tmux 原样转发 SU / SD,并尊重内部 pane 的滚动区域。
用法分工:SU 是主力 —— TUI 用它在不动光标的前提下滚动内容(日志查看器、分页输出、动态仪表板,让新数据滚入视野但光标停在状态行上)。SD 较少见;主要用于「倒带」动画,或在自定义 less 风格查看器中实现向上回滚而避免完整重绘成本。对比 LF(\n,见 c0-controls)—— 它在 *未受限* 区域底部发出时会滚动 *整屏*;SU 让你在 DECSTBM 限定的区域内滚动而不影响区域外的行,这正是分屏 TUI 得以存在的关键。对比 IL / DL(csi-il / csi-dl)—— 它们在 *光标行* 插入 / 删除行;SU / SD 对整个区域整体操作,IL / DL 对单一位置操作。相关:decstbm(DECSTBM —— 设定 SU / SD 操作的滚动区域)、cursor-move(CUU / CUD —— 只动光标不动内容的对照)、csi-il(IL —— 区域级 SD 的每行版伴侣)。
规范出处: ECMA-48 §8.3.147 (SU) / §8.3.113 (SD)
参数
| S | 向上滚动 N 行 |
| T | 向下滚动 N 行 |
示例
printf 'top\nmid\nbot\033[2S' # scroll region up 2import sys; sys.stdout.write('\x1b[1S')fmt.Print("\x1b[1S")process.stdout.write('\x1b[1S')printf("\x1b[1S");在哪里用到
实际会发出该序列的工具——把抽象字节锚定到你已经用过的命令上。
- less, more pagers`d`(下半页)与 `u`(上半页)发 SU / SD 滚动视口而不重绘状态行
- vim, neovim window scrolling`<C-d>` / `<C-u>` 与 `<C-e>` / `<C-y>` 映射到 DECSTBM 限定区域内的 SU / SD,使状态行钉住不动
- htop, btop, glances dashboards进程列表的动态刷新通过 SU 把行向上滚动,而表头位于滚动区域外保持冻结
- tmux, GNU screen split-pane redraws每个分屏运行各自的 DECSTBM 区域;每个 pane 的 SU / SD 局限于自身,不会泄漏到分隔条或其他 pane
- ncurses wgetch — refresh loop emits SU to scroll the inner window without clearing the surrounding chrome
常见问题
针对这条序列,开发者真正会去搜索的问题的简短回答。
\x1b[1S和在底行发一个\n有什么不同?- 两点。(1)光标:SU 保持光标不动;底行的 LF 会把光标下移(虽随后会被终端钳制在底行,但部分模拟器的内部行计数仍发生改变)。(2)区域意识:SU 严格在 DECSTBM 滚动区域内操作 —— 区域外的行原样冻结。LF 只滚动未受限区域;若你通过
\x1b[<top>;<bot>r缩小了滚动区域而光标停在区域外,LF 的行为由实现定义且常出意外。TUI 想要「让日志视口向上滚一行但状态栏和光标钉住不动」时,SU 一次同时满足两点。 - 为什么
\x1b[T(SD)有时会被识别为鼠标追踪上报? - 末字节
T(0x54)被重载。带一个参数时是 SD ——\x1b[<N>T将区域下滚 N 行;带五个参数(\x1b[<Pe>;<Px>;<Py>;<Pv>;<Ph>T)时则是 xterm 高亮追踪鼠标上报,来自 DECSET?1001。现代模拟器按参数个数消歧,但只匹配CSI ... T而不计参数个数的临时解析器会误判其一。如果你写这样的解析器,在派发前数清;分隔符。如果你向某个先前程序启用了高亮追踪却未关闭的终端发 SD,最好改用 IL 回退(在区域顶行发\x1b[<N>L)以彻底规避歧义。
终端支持
- 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 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 | 支持 |