阅读前清除stdin


14

我有以下bash脚本:

# do some time consuming task here
read -p "Give me some input: " input

现在您可能已经猜到,如果用户在“耗时任务”期间按下某些随机密钥,则也会考虑不需要的输入。stdin在发出read命令之前,如何清除(或至少忽略它)?


1
我自己,除非你正在写一个类似诅咒的程序,否则我会发现你想做什么才能成为你程序中的设计缺陷。UNIX / Linux具有缓冲输入(“预先输入”)的非常有用的功能,我通常使用此功能。通过你的程序,你丢弃我键入的内容,我可能会提交一个错误并停止使用你的程序,直到它被修复。
Arcege 2011年

1
一些用户习惯于在他们的程序忙于做某事时用键盘弹钢琴。我宁愿扔掉那些按键并重新开始。但你是对的,“提前输入”很有用,但并非总是如此。
rabin 2011年

Answers:


8

我不认为有一种方法可以清除stdin但是(使用bash)你可以在你要求输入之前阅读并丢弃那里的东西

#do some time consuming task here
read -t 1 -n 10000 discard 
read -p "Give me some input: " input

这会读取stdin并且超时为1秒,但如果stdin中有超过10000个字符,则会失败。我不知道你有多大的nchars参数。


我实际上在论坛上发现了这个黑客。我期待找到更好的方法。显然不是。
rabin 2011年

@rabin:如果你确实找到了一个更好的方式回到这里,我会在几个脚本中找到它。
伊恩

不幸的是,这不适用于所有的炮弹,例如破折号 :(
scai

19

在Bash 4中,您可以设置-t(超时)0。在这种情况下,read立即返回退出状态,指示是否有数据等待:

# do some time consuming task here
while read -r -t 0; do read -r; done
read -p "Give me some input: " input

6
read -d '' -t 0.1 -n 10000

如果用户无意中多次输入,则会读取多行输入


5

这对我很有用:

function clean_stdin()
{
    while read -e -t 0.1; do : ; done
}

-e在这种情况下为什么?
nhed

@nhed不再确定,也许是为了规避一些系统特定的问题
pschichtel

4

将耗时的任务包含在stdin关闭的块中:

{
     # time consuming task
} <&-

read -p "Give me some input: " input

我认为这与这个问题无关。
斯科特

但确实如此!用户希望丢弃所有输入。不允许输入就是这样 - 因为stdin关闭,所有输入都被丢弃(由系统)。这是他的问题的优雅解决方案。他让系统进行丢弃而没有编写丢弃循环的麻烦。
HiTechHiTouch 2017年

到目前为止,这似乎是最可靠的选择。
Stephen Eilert

看起来很完美但对我不起作用。我试过bash 5.0.0和4.4.19。read仍会读取# time consuming任务期间输入的第一行。此外,如果脚本不包含任何读取stdin的命令,read则在脚本终止后在交互式终端上执行未读行。有没有人成功测试过这个?
Socowi

3

基于christophjaeger的答案,我补充-s说,输入不会回显到终端,-n因此它不会等待换行。

while read -r -t 0; do
    read -n 256 -r -s
done

使用-n是一个好主意,但之前的两个答案已经提到过它。考虑到这个练习的目的是阅读并丢弃在执行之前 输入的任何内容,我不明白你认为它会做什么。read -s
斯科特

2
function clear_stdin()
(
    old_tty_settings=`stty -g`
    stty -icanon min 0 time 0

    while read none; do :; done 

    stty "$old_tty_settings"
)

clear_stdin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.