esc"键的VT100转义码是什么

5 投票
2 回答
5039 浏览
提问于 2025-04-15 20:16

我正在写一个脚本,用来操作一个基于文本的菜单系统,使用Python的telnetlib来访问串口连接。

我可以顺利地按下功能键,比如F9对应的代码是"\033OX",其中"\033"是一个特殊的转义序列。

那么,如何表示“esc”这个键呢?我原本以为只需要用"\033"就可以了,但似乎并不奏效。

2 个回答

6

在发送转义字符后,稍微等一下,比如1.5秒,这样对方就能明白这是一个独立的转义,而不是更长的一串指令的一部分。

9

在VT-100终端(或者其他使用转义序列的终端)上,并没有所谓的“ESC键转义序列”。

转义字符,ASCII码27,用来表示后面的字符序列有特殊含义。这通常会让终端进入一种简单的状态机。一般来说,规则是吞掉接收到的字符,直到看到一个字母或符号字符为止,虽然有些特殊情况,比如某些符号可能会多占用一个字符,例如ESC # 6表示双宽字符。

举个例子,在H-19 / VT-52终端上,ESC H表示回到首页,ESC E表示清屏并回到首页,ESC J表示清除到屏幕末尾,等等。VT-100系列则使用ESC [ H表示回到首页,ESC [ 2 J表示清除到屏幕末尾。

实际上,左方括号(没有右方括号)表示接下来会有一系列参数,通常是数字。ESC [ 2 J中的‘2’表示从光标到顶部(零),以及从光标到末尾(一个)。如果把J换成K,那就会清除当前行,而不是整个屏幕。这些并不是随意的。即使是ESC [ 行 ; 列 H也会接受数字行/列,例如ESC [ 12; 34 H会移动到第12行,第34列。如果不提供这些参数,就会使用默认值。

理论上,服务器不应该给你发送一个没有意义的孤立ESC字符,因为终端会等待一个序列。

当你按下功能键时,终端会发送一个ESC字符,后面跟着一些预设的序列,比如功能键、箭头或其他动作。例如,ESC [ 21 ~表示F10。

这就带来了一个实际的问题,如何发送一个字面上的孤立ESC。有两种方法。

第一种,发送ESC后延迟一段时间。主机需要负责监控不仅是接收到的内容,还有接收的时间。假设终端会立即发送其缓冲区中的字符块,它会在内部超时,并将ESC视为仅仅是ESC。这个延迟不需要很长。

第二种,要求用户每次想要发送字面ESC时按两次ESC。因为没有转义序列会包含两个ESC字符,这就表示了一种特殊情况。这就像我们在字符串中引用反斜杠字符一样,一个“\”实际上意味着一个“\”,因为我们必须满足编译器的词法阶段。在这种情况下,主机服务器就是这个角色。记住,在串口时代,也就是这些终端使用的时代,当按下一个字符时,它会立即被发送。直到多年后我们才开始模拟终端,因此需要模拟它们的转义序列,而不是从内容流中提取行为。

当然,一个“无效”的ESC序列意味着ESC是字面上的,但这需要在你采取行动之前查看后面的字节(因此需要超时解决方案)。问题是,有时这些字符会对应用程序造成副作用,甚至是很糟糕的副作用,出现有趣的情况时,试图天真地欺骗系统可能会让你陷入麻烦。例如,使用ESC空格来强制发送转义,ESC会取消一个提示,但空格意外地确认了下一个提示。

第三种解决方案是让主机完全忽略特殊功能键,直接将接收到的字节流视为字面值。例如,TECO编辑器每次按下ESC时都会向用户显示一个美元符号,因为它将这个符号用作命令分隔符,就像今天编程时使用分号一样。

撰写回答