#perl #buffer #stdin #flush
#perl #буфер #stdin #очистка
Вопрос:
Есть ли какой-либо способ очистить буфер STDIN в Perl? Часть моей программы имеет длительный вывод (достаточно времени, чтобы кто-то ввел несколько символов), и после этого вывода я запрашиваю ввод, но если символы были введены во время вывода, они «привязываются» к тому, что вводится во входной части. Вот пример моей проблемы:
for(my $n = 0; $n < 70000; $n ){
print $n . "n";
}
chomp(my $input = <STDIN>);
print $input . "n";
Выходные данные будут включать любые символы, введенные во время вывода из этого цикла for . Как я могу отключить STDIN или очистить буфер STDIN (или любым другим способом, чтобы не допускать вставки дополнительных символов в STDIN перед его вызовом)?
Комментарии:
1. Хорошо, я искал ответ на этот вопрос уже 3 дня (не каждый час каждого дня, но я бы сказал, по крайней мере, 3 или 4 часа в день) и еще не нашел ответа, на самом деле я спросил своих коллег, которые также знают и используют Perl, иони тоже не знают, поэтому я считаю, что я приложил больше усилий, чем вы подразумеваете, что я вложил, кроме того, есть ли у вас какие-либо идеи относительно того, как сделать то, что я прошу? Поскольку я уже просматривал вашу ссылку около 3 дней назад, я попытался реализовать эти функции таким образом, чтобы логически устранить эту проблему, и это не сработало.
2.
use IO::Handle;STDIN->autoflush(1);
3. Спасибо за ваш ответ, но это не решило проблему, кроме того, я помню, что чтение autoflush и flush хороши только для вывода, таких как STDERR и STDOUT, а не для ввода. Когда я попробовал то, что вы предложили, я все равно получаю символы, которые я ввел во время вывода цикла for, плюс то, что я когда-либо вводил в STDIN.
4. @JackManey: Как правило, «очистка» применяется к выводу, а не к вводу.
Ответ №1:
Похоже, вы можете выполнить это с 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 3
переходитSTDIN
в режим cbreak, что означаетSTDIN
, что после каждого нажатия клавиши происходит сброс. Вот почему…while(defined($key = ReadKey(-1))) {}
происходит. Это удаление символов, введенных пользователем во время дорогостоящего с точки зрения вычислений кода. Затем…ReadMode 0
сбрасываетсяSTDIN
, и вы можете читать,STDIN
как если бы пользователь не стучал по клавиатуре.
Когда я запускаю этот код и нажимаю на клавиатуру во время sleep(10)
, а затем ввожу какой-либо другой текст после приглашения, он выводит только текст, который я ввел после появления приглашения.
Строго говоря ReadMode 2
, он не нужен, но я поместил его туда, чтобы экран не был загроможден текстом, когда пользователь нажимает на клавиатуру.
Ответ №2:
У меня была такая же проблема, и я решил ее, просто отбросив что-либо в 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";
Комментарии:
1. — только что понял, что это работает только в том случае, если во время обработки происходит возврат, в противном случае он будет приостановлен до тех пор, пока кто-нибудь не нажмет enter
Ответ №3:
{ local $/; <STDIN> }
Это временно — ограничено областью действия блока — устанавливает $/ , разделитель входных записей, в значение undef, что указывает perl просто читать все, а не читать строку за раз. Затем считывает все, что доступно в STDIN, и ничего с этим не делает, тем самым очищая буфер.
После этого вы можете читать STDIN как обычно.
Комментарии:
1. Это не сработает.
<STDIN>
Вызов блокируется до тех пор, пока не будет прочитана «запись». Но если$/
естьundef
, конца записи быть не может, поэтому она будет блокироваться до тех пор, пока не будет достигнут EOF.