我有时使用 bash 和向上箭头键来快速获取我之前使用过的命令。令人恼火的是有时当我这样做时,我得到的是一个[A
而不是之前的命令。在网上做了一些研究后,看起来这是一个代表发送到计算机的向上箭头键的键代码。
我似乎无法在网上找到任何答案。我怎样才能阻止这种情况再次发生?
答案1
背景
该序列实际上是Escape[A,并且它是被采用的集合的一部分埃克玛1976年作为标准ECMA-48,多年来被 ANSI 作为独立但几乎相同的标准支持(后来撤回),并得到 ANSI 的批准ISO/IEC 6429在途中。这种多重标准化的结果是,尽管它们经常被引用为 ANSI 转义码,但它们应该正确地称为 ECMA-48 控制函数*。
解释
在屏幕上看到而不是在操作上看到的通常原因[A
是初始转义代码已被意外吸收。除非我先按 ,否则我无法在键盘上重现此内容Ctrl V,这告诉终端线路驱动程序将下一个字符作为文字处理。
因此,我们可以获得这个序列Ctrl VEscape[A,产生可见的输出[A
。
您会注意到,如果您快速连续按下字符序列,Escape[A光标确实会向上移动。但是,如果您在第一个字符后暂停,您将无法获得光标移动,这是因为转义字符具有与其关联的超时。在连接到 UNIX 系统的慢速串行线路上,这曾经是一个真正的问题,最接近的等价物是慢速或间歇性网络连接,在此序列传输期间有短暂的滞后。
预防
现在回答你的问题,如何防止这种情况发生。如果您处于间歇性网络连接上,您无能为力,除非可以使用备用序列之一,例如……Escapek在“vi 模式”( ) 下进行命令编辑期间可用。kkset -o vi
* 我想,就像 JavaScript 应该被称为 ECMAScript 一样
答案2
正如 @roaima 所提到的,这曾经是一个众所周知的问题,在通过网络或串行线路运行的程序中经常出现,其中传输延迟会干扰试图区分普通文本的程序(例如 vi)。逃脱字符来自转义序列。由于大多数用户不再在分时服务器上运行程序,因此他们不会注意到这一点。
问题是程序必须延迟一段“短”时间以允许它查看是否有逃脱字符后面跟着其他字符可以成为其中之一的一部分转义序列它正在等待。传统上,特殊键(例如光标键、功能键等)作为转义序列发送。
如果您碰巧按住某个键,以便启动按键重复功能,那么发送这些转义序列的速度可能比(某些)程序读取它们的速度更快。当这种情况发生时,各个字符之间的时间往往会增加,并最终超过分配给区分字符的“短”时间。逃脱字符与转义序列。
readline(一部分/捆绑)bash 尝试区分不同的字符序列,这些字符序列(如 vi)可能以相同的方式开始。它有一个功能可以改变这个“短”时间:
8.3.1Readline 初始化文件语法
keyseq-timeout
指定 Readline 在读取不明确的按键序列(可以使用到目前为止读取的输入形成完整的按键序列,或者可以采用额外的输入来完成较长的按键序列)时等待字符的持续时间。如果在超时时间内没有收到输入,Readline 将使用较短但完整的按键序列。 Readline 使用此值来确定当前输入源(默认为 rl_instream)上的输入是否可用。该值以毫秒为单位指定,因此值 1000 意味着 Readline 将等待一秒钟以获取其他输入。如果此变量设置为小于或等于零的值,或者设置为非数字值,Readline 将等到按下另一个键来决定完成哪个键序列。默认值为 500。
也就是说,您可以将其放入您的~/.inputrc
文件中:
set keyseq-timeout 0
readline 将无限期地等待这些光标键。缺点是,当您碰巧键入一些与其库中的某些字符相匹配的字符时,它可能会产生意外的结果。
答案3
在我的终端 shell(使用 bash 的 Konsole)中,我可以^[[A
按照Ctrl+V已接受的答案中所述进行重现。然而,与我接受的答案不同可以[A
像通过按专门询问的问题一样自行复制EscArrowUp
当您无意中按下 时Esc,您可以再次按下它来阻止其逃逸箭头按键的第一部分,从而防止[A
出现。
答案4
所有的答案都非常好。快速而肮脏的方法是使用 h、j、k、l 作为方向键。或者安装完整的 vim 包。如果我没记错的话,Ubuntu 发行版默认为 vim??-runtime,如果你只安装 vim??然后问题就会自行“解决”。 ??是最新的完整包版本。关于Ubuntuapt-cache search vim
会告诉你。
h=左,j=下,k=上,l=右