脱字符表示法与ANSI转义序列

2021年4月16日

读者往往从“如何在Bash输出颜色”接触到ANSI转义序列。当探索Bash逐渐深入,读者会在Bash高级用法的特殊按键、键绑定里看到脱字符表示法与ANSI转义序列。本文辨析脱字符表示法与ANSI转义序列。本文不需要读者掌握“输出颜色”的技能。

本文将用带框文字代表键盘上的特殊按键,如Esc代码ESC键、ctrl-d代表按住ctrl和d。没有框的文字代表逐字输入,如[31m表示依次按下[、3、1、m四个键。

物理ESC键在Bash的内部表示

$ cat
Esc[31mhello
ctrl-d

会看到hello变为红色。

命令行的实际显示是^[[31mhello,说明esc键用^[表示。

如图,但第二次就不行了,是为什么呢?原来,第二次我直接按键盘上的^和[,不是通过Esc键生成的。这说明,Bash在显示时不会区分逐字字符和特殊字符。

到目前为止,我们已经确认了键盘上的物理ESC键与^[关系。我们把^[称为Esc的表示法。^叫做脱字符,所以完整名称叫做脱字符表示法

注:在cat以外输入ESC键的方式是先按ctrl-v,再按ESC。[1]

转义输入ESC

我们已经在cat实验过,如果逐字打^和[,并不会代表Esc。这是一个概念误用。脱字符表示法是用来表示的,并不用来输入。要输入,必须用ANSI转义序列

记住ESC的ASCII code是十进制27,八进制033,十六进制x1b。在Bash,八进制一般前面加0,十六进制前面加x。注:Bash把\e也解析为ESC。

$ echo -e "3[31mhello"
$ echo -e "\e[31mhello"

都会输出红色的hello。

脱字符表示法与ANSI转义序列“同台”“王见王”

为了直观地比较脱字符表示法与ANSI转义序列,让它们“同台”,我们下面用ZSH的bindkey函数。bindkey -L输出当前已绑定的所有键,它当然使用脱字符表示法。

$ bindkey -L
bindkey "^X~" _bash_list-choices
bindkey "^Y" yank
bindkey "^[Q" push-line
bindkey "^[T" transpose-words
bindkey "^[U" up-case-word
...

以ESC+u为例,在下图我首先用上面介绍的“在cat以外输入ESC键的方式”输入ESC,注意到^[是反色的,因为ZSH可以对特殊字符有特殊显示。后面两行我用x1b、033转义序列。不论我怎么输入,bindkey的显示始终使用脱字符表示法。

参考资料

  1. . Bash Reference Manual. . [2021-04-17].