shell脚本响应keypress

j0h*_*j0h 15 bash shell input keypress

我有一个shell脚本,基本上就是这样的

while true; do
    read -r input
    if ["$input" = "a"]; then 
        echo "hello world"           
    fi
done
Run Code Online (Sandbox Code Playgroud)

这一切都很好,很好,但我只是意识到必须点击ENTER在这种情况下提出了一个严重的问题.我需要的是脚本在按下键时响应,而不必按Enter键.

有没有办法在shell脚本中实现此功能?

pac*_*lik 21

read -rsn1
Run Code Online (Sandbox Code Playgroud)

期待只有一个字母(并且不要等待提交)并保持沉默(不要写回那封信).

  • 如果您需要检查输入是否可用,请尝试添加 `-t 0.01` 以等待几分之一秒,如果没有按键等待,则放弃。如果你想要一个非常紧凑的循环,较小的数字仍然可能完全没问题。非正式实验表明 0.00001 有效,但 0.000001 太小了。 (2认同)

Don*_*rek 10

所以最后的工作片段如下:

#!/bin/bash

while true; do
read -rsn1 input
if [ "$input" = "a" ]; then
    echo "hello world"
fi
done
Run Code Online (Sandbox Code Playgroud)


小智 6

另一种方法,以非阻塞方式(不确定它是否是您想要的)。您可以使用 stty 将最小读取时间设置为 0。(如果 stty sane 之后不使用,则有点危险)

stty -icanon time 0 min 0
Run Code Online (Sandbox Code Playgroud)

然后像往常一样运行你的循环。不需要 -r。

while true; do
    read input

    if ["$input" = "a"]; then 
        echo "hello world"           
    fi
done
Run Code Online (Sandbox Code Playgroud)

重要的!完成非阻塞后,您必须记住使用设置 stty 恢复正常

stty sane
Run Code Online (Sandbox Code Playgroud)

如果您不这样做,您将无法在终端上看到任何内容,并且它似乎会挂起。

您可能希望为 ctrl-C 设置一个陷阱,就好像脚本在您将 stty 恢复正常之前退出一样,您将看不到您输入的任何内容,并且终端似乎已冻结。

trap control_c SIGINT

control_c()
{
    stty sane
}
Run Code Online (Sandbox Code Playgroud)

PS 此外,您可能还想在脚本中放置一个 sleep 语句,这样您就不会用完所有的 CPU,因为这将尽可能快地持续运行。

sleep 0.1
Run Code Online (Sandbox Code Playgroud)

PSS 似乎只有当我像以前一样使用 -echo 时才会出现挂起问题,因此可能不需要。我将把它留在答案中,因为将 stty 重置为其默认值以避免将来出现问题仍然很好。如果您不希望您输入的内容出现在屏幕上,您可以使用 -echo。