Ctrl+H 为什么是退格
npm 包 charcodes 里的 backSpace = 8 并非随意指定——它来自 1963 年的 ASCII 表。ASCII 一共 128 个位置,前 32 个 (0–31) 加上最后一个 (127) 全是看不见的控制字符:它们不是「字」,而是发给电传打字机 teletype
的指令——退一格、走一行纸、摇回行首、响个铃。更关键的是,Ctrl 键的本职工作就是把字母「变成」控制字符:按住 Ctrl 等于把字母编码的高两位清零,所以 Ctrl+H = 72 & 0x1F = 8 = 退格。这一页把整张表和这条算式摊开看。
1 · 整张 ASCII 表——点任意格子看它的身份
蓝色 = 控制字符(0–31 与 127),白色 = 可打印字符 (32–126),橙色 = 空格。注意控制区和字母区的纵向对应:每个控制字符正上方差 64 的位置,就是它的 Ctrl 字母。
为什么 DEL 偏偏是 127,不与其他字符同处 0–31? 因为纸带。早年程序打在穿孔纸带上,打错了没法擦——唯一的补救是把那一列七个孔全部打穿,约定「全是孔 = 作废」。七位全 1 正是 1111111 = 127。DEL 是物理介质留在编码表里的活化石。
2 · Ctrl 的本职:清零高两位,字母变指令
电传打字机时代没有「快捷键」概念——Ctrl 是个修饰电路:按住它,键发出的编码会被按位与 0x1F(保留低 5 位)。选一个字母,看这步位运算怎么把它变成控制字符:
这就是终端快捷键的「词源」: Ctrl+I = Tab、Ctrl+J = 换行、Ctrl+M = 回车、Ctrl+[ = Esc(所以 Vim 里 Ctrl+[ 能退出插入模式)、Ctrl+C = ETX(被 Unix 拿去当中断信号)。控制字符的「caret notation」写法 ^H ^[ 也由此而来——^X 就读作 Ctrl+X。在终端里连按 Backspace 有时会看到 ^H^H^H,正是它的本名。
3 · 键盘上活下来的控制字符
128 个里今天还印在键帽上 / 天天路过你字符串的,其实就这几个:
| 字符 | code | caret | 转义 | 键盘 | 今天在哪 |
|---|---|---|---|---|---|
| NUL 空字符 | 0 |
^@ |
\0 |
— | C 字符串结尾 · 纸带上的空白段 |
| BEL 响铃 | 7 |
^G |
\a |
— | 终端里 echo 它会「叮」一声 |
| BS 退格 | 8 |
^H |
\b |
Backspace | 键盘 Backspace · charcodes 的 backSpace |
| HT 水平制表 | 9 |
^I |
\t |
Tab | 键盘 Tab · 缩进之争的主角 |
| LF 换行 | 10 |
^J |
\n |
(Enter 的一半) | Unix 换行符 |
| CR 回车 | 13 |
^M |
\r |
Enter | Windows 换行 = CR+LF · HTTP 行尾 |
| ESC 转义 | 27 |
^[ |
\x1B |
Esc | 键盘 Esc · ANSI 彩色转义序列的开头 |
| DEL 删除 | 127 |
^? |
— | (Mac 上 Delete 发的是它) | 纸带「打满孔作废」的活化石 |
CR 和 LF 为什么是两个字符? 打字机上「换行」真的是两个机械动作:CR(carriage return)把滚筒摇回行首,LF(line feed)把纸卷上一行。电传机照搬了这套,于是文本世界从此分裂:Unix 只留 \n、老 Mac 只留 \r、Windows
两个都要 \r\n——git 的 autocrlf、HTTP 头的 CRLF 行尾,根都在打字机的两个零件上。