假设一个应用程序要求键盘输入,而我按住一个键一段时间。
现在应用程序正在响应按键,但随着进程的进展,速度正在变慢。
这个想法是清除存储在缓冲区某处的所有这些传入的按键,以便让应用程序停止其糟糕的操作。
答案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
即在bash
shell 中尝试,或者查看这个文档) 并使用 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 -echok
echo
echok
read -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
将确保启用它们(请注意,它们缺少减号 ( -
) 前缀),否则在该脚本退出后,您将看不到命令提示符中键入的内容(即,禁用您键入内容的回显)。请注意,此示例并不是进入此状态的唯一方法,但它是一个帮助我重现当我仅使用而没有时
回显被禁用的问题的示例。read
clrbuf
stty
更好的方法可能是在调用之前保存echo
和的状态,然后恢复状态。但这容易出现竞争条件(如果禁用回显的程序在我们的并行期间重新启用它们),因此可能会让用户面临无法回显终端的风险(当我们将它们恢复为禁用时)。就我个人而言,我不会冒险实施这种变体。echok
read -s ...
read -s
stty