清空 Perl STDIN 缓冲区

10

有没有办法在Perl中清空STDIN缓冲区?我的程序的一部分输出很长(足够时间让某人输入几个字符),在输出之后我会要求输入,但如果在输出期间输入了字符,它们就会“附加”到输入部分输入的任何内容中。以下是我的问题示例:

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

输出将包括在该for循环期间输入的任何字符。我如何禁用STDIN或刷新STDIN缓冲区(或者任何其他不允许在调用之前向STDIN插入额外字符的方法)?


好的,我已经寻找这个问题的答案三天了(不是每天每小时,但我会说每天至少3或4个小时),但我还没有找到答案,事实上,我问过我的同事,他们也知道和使用Perl,但他们也不知道,所以我相信我已经付出了比你暗示的更多的努力,抛开这些,你有任何想法如何做我所要求的吗?因为我已经大约三天前查看了您的链接,尝试以逻辑方式实现这些功能来解决此问题,但它没有起作用。 - mcwillig
1
use IO::Handle;STDIN->autoflush(1); - user554546
谢谢您的回答,但是这并没有解决问题。我记得阅读过autoflush和flush只适用于输出,例如STDERR和STDOUT,而非输入。当我尝试您提供的方法后,我仍然会在for循环输出期间获得我输入的字符以及从STDIN输入的任何内容。 - mcwillig
4
通常,“flushing”适用于输出,而不是输入。 - Keith Thompson
3个回答

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)期间敲击键盘,然后在提示符后输入一些其他文本时,它只打印出我在提示符出现后输入的文本。

严格来说,ReadMode 2 不是必需的,但我把它放在那里是为了防止用户在键盘上敲击时屏幕充满了文本。


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";

刚刚意识到这只在处理期间有返回时有效,否则它会暂停,直到有人按回车键。 - Sy Bernot

-4
{ local $/; <STDIN> }

这段代码暂时将 $/(输入记录分隔符)的作用域限制在块内,并将其设置为 undef,这告诉 Perl 一次性读取所有内容而不是逐行读取。然后从 STDIN 中读取所有可用的内容并不做任何处理,从而刷新缓冲区。
之后,您可以像平常一样读取 STDIN。

2
这样行不通。<STDIN>调用会阻塞,直到可以读取“记录”。但是如果$/是未定义的,则可能没有记录结束,因此它将一直阻塞,直到达到EOF。 - mob

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接