如何清除键盘缓冲区?

如何清除键盘缓冲区?

假设一个应用程序要求键盘输入,而我按住一个键一段时间。

现在应用程序正在响应按键,但随着进程的进展,速度正在变慢。

这个想法是清除存储在缓冲区某处的所有这些传入的按键,以便让应用程序停止其糟糕的操作。

答案1

您必须指出应用程序的类型:终端(POSIX 系统调用、curses 或 stdio API)、Qt、Gtk……

如果它是一个终端(系统调用),您可以使用select系统调用并验证标准输入上是否有可用内容,如果是,则读取它。

这更像是一个编程问题。

答案2

我将以这样的意义来回答标题问题How to clear the keyboard buffer?:到目前为止输入的所有内容,以及被视为等待程序使用的输入的内容,都将被清除,下面是我在一个chmod a+x clrbuf名为的可执行文件(即)中执行此操作的方法clrbuf,该文件会默默地使用输入:

#!/bin/bash
read -r -t 0.1 -s -e --
stty echo echok
exit 0

解释:
总结:默默地消耗所有输入,如果没有输入,则在 0.1 秒(100 毫秒)后退出,然后使用stty以确保read没有禁用用户输入内容的回显,这在某些情况下可能会发生。

这是使用 /bin/bash 的内部read命令($ help read即在bashshell 中尝试,或者查看这个文档) 并使用 coreutils 包(在 Gentoo 上)的一部分 /bin/stty。

它会读取所有等待读取的内容并忽略它。
例如,如果你运行sleep 5 ; clrbuf然后开始输入类似hello+enter 键的内容并停止输入,则 5 秒后clrbuf运行并吞噬你输入的内容,因此终端提示符之后不会获取该输入。像这样:

$ sleep 5; clrbuf
hello

$ sleep 5; notclrbuf
hello
bash: notclrbuf: command not found
$ hello
bash: hello: command not found

read的争论是
不需要--的,它标志着所有争论的结束,这只是我的一个习惯。

$ read -r --

$ read -- -r
bash: read: `-r': not a valid identifier

因为那里需要一个变量标识符来放置读取的结果。

-r “不允许使用反斜杠转义任何字符。反斜杠不作为转义符。反斜杠被视为行的一部分。特别是,反斜杠换行符对不能用作行延续。”(来自help read那份文件

$ read -- a ; echo $a
\\
\

$ read -r -- a ; echo $a
\\
\\

-t TIMEOUT “如果在 TIMEOUT 秒内未读取完整行输入,则导致读取超时并返回失败。如果读取未从终端或管道读取输入,则此选项无效。”(来自同一文档-t 0.1用于read当没有待处理的输入时,0.1 秒后自动退出。

-s “静音模式。如果输入来自终端,则不会回显字符。”(来自同一文档
例如,如果我输入“hi”+enter,一次:

$ sleep 5; read  -r -t 0.1  -e -- 
hi
hi

$ sleep 5; read  -r -t 0.1 -s -e -- 
hi

-e “readline 用于获取行”。出于某种原因,我注意到如果没有这个参数它就无法工作。我不记得为什么,但我注意到它对于“GNU bash,版本 5.0.16(1)-maint (x86_64-pc-linux-gnu) 提交 3235014e5b3d227ccd617b0be72d897eb476d23d on devel branch Date: Mon Apr 20 10:11:53 2020 -0400”是正确的。值得一提的是,我已经在 Gentoo 上使用 USE=bundled-readline 编译了 bash,也许这就是为什么它目前对-e我来说没有它也能工作的原因。我不确定。

exit 0是始终确保从脚本返回成功,以防万一clrbuf在另一个 bash 脚本中使用set -e(如果在调用脚本后出现不同于 0 的退出代码,则会导致该脚本退出clrbuf)(“ -e 如果命令以非零状态退出,则立即退出。”)。例如:

#!/bin/bash

set -e
test 20 == 0
#^ our script will exit due to the above, because the above returned exit code 1

echo Done
#^ this is not reached

为什么stty echo echok需要?
由于(又名 silent)的作用与(即 disable和)read -s相同,为了确保用户能够回显所输入的内容,在某些情况下,我们会确保在完成后启用回显。 以下示例(c.bash)说明了何时可能发生这种情况:stty -echo -echokechoechokread -s

#!/bin/bash

stty
for i in 1 2 3 4; do
  echo 'a' & #required
  read -r -t 0.1 -s -- &
  #echo "$?" #is 0
done
wait
stty
stty echo echok

输出如下:

$ ./c.bash 
speed 38400 baud; line = 0;
erase = ^H;
-brkint -imaxbel iutf8
a
a
a
a
speed 38400 baud; line = 0;
erase = ^H;
-brkint -imaxbel iutf8
-echo -echok

正如您在最后看到的,-echo -echok与调用之前启用它们时相比,它们被设置为(禁用)的新内容read -s ... &(因此根本不由 stty 打印)。最后一行stty echo echok将确保启用它们(请注意,它们缺少减号 ( -) 前缀),否则在该脚本退出后,您将看不到命令​​提示符中键入的内容(即,禁用您键入内容的回显)。请注意,此示例并不是进入此状态的唯一方法,但它是一个帮助我重现当我仅使用而没有时
回显被禁用的问题的示例。readclrbufstty

更好的方法可能是在调用之前保存echo和的状态,然后恢复状态。但这容易出现竞争条件(如果禁用回显的程序在我们的并行期间重新启用它们),因此可能会让用户面临无法回显终端的风险(当我们将它们恢复为禁用时)。就我个人而言,我不会冒险实施这种变体。echokread -s ...read -sstty

相关内容