Следующий код работает вид штрафа:
open( PIPE, '-|', 'ant' );
for( <PIPE> ) {
print;
}
Однако это не делает то, что я хочу. Так как сборка Муравья может занять 5 минут, я хотел бы видеть вывод линию за линией. Вместо этого я получаю весь вход в конце процесса.
Смотря на него с отладчиком Perl, Perl ожидает в оператора, пока Муравей не завершается. Почему это?
Просто для полноты (проблема была решена, как указано в комментарии к ответу Ури) проблема возникла из-за того, что выражение for
оценивает <>
оператор в контексте списка ( см. ), что эквивалентно следующему:
foreach $line (@lines = <PIPE>) {
print $line;
}
В контексте списка оператор <>
пытается прочитать все строки со своего ввода присвоить списку - а ввод поступает от процесса, он будет блокироваться до тех пор, пока процесс не закончится. Только после этого он попадет в тело петли.
Альтернативный синтаксис
while( <PIPE> ) {
print;
}
вместо этого эквивалентен
while( $line = <PIPE> ) {
print $line;
}
, то есть он потребляет каждую строку из ввода в каждой итерации цикла, и это то, что нужно сделать в этом сценарии.
Я считаю, что проблема в буферизации. Вы можете сделать дескриптор файла горячим (небуферизованным) следующим образом:
select PIPE;
$| = 1; # the pipe is just a coincidence. that's the variable's name
select STDOUT; # select it back
Это должно отключить буферизацию для PIPE. Я читал о чем-то подобном в Learning Perl, 5TH . См. Также и . Вероятно, вам также следует убедиться, что буферизация не происходит где-то еще.
РЕДАКТИРОВАТЬ: OP опубликовал, что заменил на на , в то время как решил проблему
, теперь я думаю, что понимаю. , в то время как
получает каждую строку и запускает цикл, тогда как for
действует как foreach
и first получает все строки (ему нужен контекст списка) и , затем перебирает строки.
Нашел. Проблема в выражении «for».
Следующий код работает, как ожидалось
open( PIPE, '-|', 'ant' );
while( <PIPE> ) { # replacing 'for' with 'while'
print;
}
Я не знаю причины, но теперь он работает.