您好我试图暂停执行一个进程,以便用户在5秒后才能进行多次输入。我尝试使用sleep但是sleep只是停止然后执行用户在进程处于睡眠状态时运行的所有输入,我不希望在程序休眠时读取任何输入。
我想要的例子:聊天机器人 输入1:嗨 输出:"程序回复" 输入2(在5秒之前):"什么是新的" - 没有输出 - 输入3(已经过了5秒):"你好吗" 输出:我很好。
sleep命令的作用示例: 输入1." hi" 输出"嘿" 输入2(在5秒之前):"什么是新的" - 没有输出 - 等待 输入3:"你好吗" 输出:"并不多是新的" 输出:"我很好"
答案 0 :(得分:1)
您可以在5秒钟后读取并丢弃用户的输入
# 1.
read -p "prompt 1: " first_thing
sleep 4
# this reads and ignores whatever the user has typed during the sleep
while read -t 1 _garbage; do :; done
# 2.
read -p "prompt 2: " next_thing
如果没有任何内容可读, read
s -t 1
选项超时为一秒。
测试
带输入
$ read -p "prompt 1: " first_thing; sleep 4; while read -t 1 _garbage; do :;done ; read -p "prompt 2: " next_thing
prompt 1: foo
bar
baz
prompt 2: qux
$ echo $first_thing $next_thing
foo qux
no" extra"在第二次读取之前输入 - 进程没有"挂起"等待输入
$ read -p "prompt 1: " first_thing; sleep 4; while read -t 1 _garbage; do :;done ; read -p "prompt 2: " next_thing
prompt 1: hello
prompt 2: world
$ echo $first_thing $next_thing
hello world
答案 1 :(得分:1)
这绝非易事,您需要更具体地说明您希望脚本如何响应键盘输入。
没有办法锁定"键盘;用户可以在他们认为合适时继续打孔。如果您满足于要回显的键,但您希望忽略输入,则可以执行以下操作:
# Beware! Read the entire answer; don't just use this command
timeout 5 bash -c 'while :;do read -s -d ""; done'
timeout
实用程序运行命令,在指定的秒数过后将其终止;指定的数字可以是小数。 read
命令周围的循环是必要的,因为只要按下Enter键,read
就会终止; while :; do
是"永远循环的标准习语"。
timeout
命令是Gnu coreutils的一部分。如果你没有它,也许是因为你使用的是BSD衍生物,你可能会找到替代品。有一个FreeBSD命令,可能在其他BSD上可用,包括Mac OS X,称为timelimit
;我相信正确的调用是将timeout 5
替换为timelimit -t 5 -s9
,但我没有任何简单的测试方法。
您需要让read
命令立即实际读取输入,而不是等到按下Enter键。否则,在read
终止后,下一个命令仍然可以使用键入的输入。
有几种方法可以做到这一点。一种是使用-n 1
标志使read
在每个字符后返回;另一个是使用-d ""
将输入字符的结尾设置为NUL
,这具有将读取放入一次一个字符模式的副作用。
此外,您可能希望抑制在读取循环中按下的键的回声。你可以通过在-s
命令中添加read
标志来做到这一点,但是这样做会产生副作用,即将终端留在"没有回声" read
命令中断时的模式。 [注1]
不幸的是,您可能会发现终端设置已永久更改,因为当read
命令导致timeout
被杀时,它没有机会恢复终端设置。因此,您最终会得到一个不会回显的终端,不会处理退格和其他行编辑命令,并且不会在其他问题中使用Ctrl-D。
要避免此问题,您需要保存并恢复终端设置。您可以使用stty
命令执行此操作,如下所示:
# Save the terminal settings
saved=$(stty -g)
# Ignore input for 5 seconds, suppressing echo
timeout 5 bash -c 'while :;do read -s -d ""; done'
# Restore the terminal settings
stty "$saved"
如果您不抑制回声,您会发现输入提示可能与忽略的输入显示在同一行。您可以通过输出"回车/擦除到行尾来避免这种情况。提示前的控制序列:
tput cr; tput el; read -p "Give me some input: "
答案 2 :(得分:0)
@glenn的答案是一个很好的答案! 也许你前面不知道你要睡多久(你在打电话 其他一些功能)。 当您只想刷新输入队列时,可以尝试类似的方法:
echo "What is your name?"
read name
echo "Please be quiet for 5 seconds"
sleep 5
smalltime=0.000001
read -t ${smalltime} -s garbage
while [ -n "${garbage}" ]; do
echo "Flushing $garbage"
read -t ${smalltime} -s garbage
done
echo "Hello ${name}, please say something else"
read y
echo "You said $y"