在 bash 中,我按ctrl+v开始逐字插入。在逐字模式下,我按下Esc键,bash 显示^[
。我将其重定向到 file esc
。
同样在逐字模式下,我按ctrl键[,bash 显示^[
。我将其重定向到 file ctrl
。
接下来我对比两个文件,发现是一样的!
$ echo '^[' > esc
$ echo '^[' > ctrl
$ diff esc ctrl
$
为什么Ctrl+[和Esc会产生相同的内容?
在^[
这儿C0 和 C1 控制代码?如果是这样,维基文章说^[
是 Escape,那么为什么ctrl+[也是 Escape?
根本问题是我想检查并创建一个键绑定。
(zsh)$ bindkey -L
...
bindkey "^['" quote-line
...
那么我需要输入ESC+'
or吗ctrl+[+'
?
答案1
这看起来遵循与 Ctrl-A 相同的逻辑,即^A
字符代码 1,并^@
用于表示 NUL 字节。在这里,^
是用另一个键来表示 Ctrl 的常见方法。
即,输入给出的字符代码为Ctrl-foo富位 6 清零,字符代码减少 64。因此,A
是字符代码 65,^A
是字符代码 1;@
为 64,^@
为 0,NUL;也是[
91,也是^[
27,ESC。只是对于 ESC 你也有一个单独的键,但你也有 Enter 和 Tab 键,它们也会产生控制字符,所以这并不是什么不寻常的事情。
当然,现代系统的工作方式可能还取决于其他因素,例如键盘映射和键绑定的设置方式。也不要问我对于 < 64 的字符代码如何工作,例如。我在终端上尝试了一下,给出了 NUL 字节。Ctrl-something^1
Ctrl-space
答案2
将文本终端与文本终端应用程序(如 bash)一起使用时,您无法区分特殊键(如Esc、Tab、Enter和 )Backspace及其各自的控制字符([ IM/JH/?)。同样,您无法区分数字行和数字键盘上的数字。其他一些键(箭头、功能键、向上/向下翻页等)会产生多个字符序列。
然而,在图形环境(X11、wayland)中,按键生成与按键关联的事件,这些事件独立于(但链接到)字符映射,而与它是单个还是多个字符映射无关。如果图形应用程序选择这样做,它可以区分大多数这些键。 (在某些情况下,键可能仍然具有无法区分的映射,但这种情况很少见,并且取决于键的映射方式。)
基本上,图形终端应用程序选择不区分这些键和键序列,并且通过文本 pty,无论如何它都没有办法将差异传达给底层文本应用程序。
例如,Backspace传统上可以将键映射到Ctrl-H或Ctrl-?。在图形终端中,有一项设置可以选择将其映射到哪一个。因此,图形终端应用程序可以检测差异并更改映射,但在终端中运行的文本应用程序则不能。
答案3
长话短说:历史。
“为什么”可以追溯到 ASCII 在其标准化之前的十年中所做出的设计决策:ISO 6461967年。
当时大多数终端都是硬拷贝打印类型,而且它们的键盘通常根本没有按键ESC。如果有人想要发送 ASCIIESC
代码 27,他们可以通过输入 ctrl-[; 来实现。尽管这样做没有什么意义。
当这些新型“玻璃电传打字机”终端在 1970 年代流行时,它们更广泛地使用了代码 27,因此大多数(但不是全部)都有 ESC 键。
需要强调的是,到目前为止,唯一的用途ESC
是生成 ASCII 代码 27,终端将其理解为“更改为下一个字节将被视为命令而不是显示内容的模式”。
再过十年,出现了各种窗口系统,ESC 键出现了一种全新的用途:取消当前操作。
然而这不适用当您使用终端时,即使在窗口环境中也是如此。相反,您仍然得到 1967 年 ASCII 所规定的相同行为。
至于为什么 ctrl 键会这样做,@user10489 的另一个答案解释了这一点。