2011-09-29 70 views
10

有什么方法可以清除Perl中的STDIN缓冲区?我的程序的一部分有很长的输出(有足够的时间让某人输入几个字符),然后在输出之后要求输入,但是如果在输出过程中输入了字符,它们就会被“粘贴”到任何在输入处输入的内容部分。这里是我的问题的一个例子:Flushing Perl STDIN缓冲区

for(my $n = 0; $n < 70000; $n++){ 
    print $n . "\n"; 
} 
chomp(my $input = <STDIN>); 
print $input . "\n"; 

输出将包括在该for循环的输出期间输入的任何字符。我怎么能禁用STDIN或刷新STDIN缓冲区(或者在调用它之前不允许额外的字符被插入到STDIN中)?

+0

好吧,我一直在寻找的答案,这个问题的3天,现在每隔一小时(不,但我会说至少每天3或4小时)并且还没有找到答案,实际上我问了我的同事,他们也知道并使用Perl,他们也不知道,所以我确实相信我已经投入了比你更多的努力,暗示我已经投入了,除此之外,你对于如何去做我所要求的有什么想法吗?因为我大约3天前已经浏览了你的链接,试图以一种能够在逻辑上解决这个问题的方式来实现这些功能,并且它不起作用。 – mcwillig

+1

'使用IO :: Handle; STDIN-> autoflush(1);' – 2011-09-29 20:48:32

+0

谢谢你的回答,但是,这并没有解决问题,另外,我记得阅读autoflush和刷新只适用于输出,例如作为STDERR和STDOUT,而不是输入。当我尝试了你所建议的内容时,我仍然可以看到我在输入for循环期间输入的字符以及我在STDIN中输入的内容。 – mcwillig

回答

13

它看起来像您可以用Term::ReadKey模块实现这一点:

#!perl 

use strict; 
use warnings; 
use 5.010; 

use Term::ReadKey; 

say "I'm starting to sleep..."; 
ReadMode 2; 
sleep(10); 
ReadMode 3; 
my $key; 
while(defined($key = ReadKey(-1))) {} 
ReadMode 0; 
say "Enter something:"; 
chomp(my $input = <STDIN>); 
say "You entered '$input'"; 

这里发生了什么:

  • ReadMode 2意味着“输入模式为普通模式,但回声关闭”。这意味着用户在使用昂贵的计算代码时所做的任何键盘操作都不会回显到屏幕上。它仍然进入STDIN的缓冲区,所以...
  • ReadMode 3STDIN转为cbreak模式,意为STDIN种类在每次按键后都会被刷新。这就是为什么...
  • while(defined($key = ReadKey(-1))) {}发生。这将清除用户在计算繁琐代码期间输入的字符。然后...
  • ReadMode 0重置STDIN,您可以从STDIN读取,就好像用户没有敲击键盘一样。

当我sleep(10)中运行这段代码和Bang在键盘上,然后进入后提示某些其他文本,只打印出我输入的提示出现后的文本。

严格来说,ReadMode 2不是必需的,但是我把它放在那里,所以当用户敲击键盘时,屏幕不会与文本混杂在一起。

-4
{ local $/; <STDIN> } 

这将暂时 - 限于块的范围 - 设置$ /,输入记录分隔符,是民主基金,它告诉Perl,只是看什么,而不是每次读一行。然后读取STDIN上可用的所有内容,并不对其执行任何操作,从而刷新缓冲区。

之后,您可以像平常一样阅读STDIN。

+2

这不起作用。 ''呼叫阻塞,直到可以读取“记录”。但是如果'$ /'是'undef',则记录可能没有结束,所以它会阻塞,直到到达EOF。 – mob

0

我有同样的问题,并通过这样的处理后只是放弃任何东西STDIN解决它:

for(my $n = 0; $n < 70000; $n++){ 
    print $n . "\n"; 
} 
my $foo=<STDIN>; 
print "would you like to continue [y/n]: "; 
chomp(my $input = <STDIN>); 
print $input . "\n"; 
+0

- 刚刚意识到这只适用于处理过程中有回报,否则它会暂停,直到有人点击输入 –