Как получить вывод из канала Perl, когда он станет доступным? - PullRequest
7 голосов
/ 24 мая 2010

Следующий код работает вроде отлично:

open( PIPE, '-|', 'ant' );
for( <PIPE> ) {
    print;
}

Однако, это не делает то, что я хочу. Поскольку сборка Ant может занять 5 минут, я бы хотел видеть вывод построчно. Вместо этого я получаю весь ввод в конце процесса.

Глядя на это с помощью отладчика Perl, Perl ждет оператора for, пока не завершится Ant. Почему это?

Ответы [ 3 ]

8 голосов
/ 24 мая 2010

Просто для полноты (проблема была решена, как указано в комментарии к ответу Ури), проблема возникла потому, что выражение for оценивает оператор <> в контексте списка ( см. ), эквивалентно следующее:

foreach $line (@lines = <PIPE>) {
    print $line;
}

В контексте списка оператор <> пытается прочитать все строк из своего ввода для выравнивания по списку - и ввод поступает из процесса, он блокируется до завершения процесса. Только после этого он войдет в тело цикла.

Альтернативный синтаксис

while( <PIPE> ) {           
    print; 
} 

эквивалентно

while(  $line = <PIPE> ) {
    print $line;
}

Т.е. он потребляет каждую строку из входных данных в каждой итерации цикла, и это то, что вы хотите сделать в этом сценарии.

3 голосов
/ 24 мая 2010

Я считаю, что проблема в буферизации.Вы можете сделать дескриптор файла hot (небуферизованный) следующим образом:

select PIPE;
$| = 1; # the pipe is just a coincidence. that's the variable's name
select STDOUT; # select it back

Это должно отключить буферизацию для PIPE.Я читал о чем-то подобном в Learning Perl, 5TH .Смотрите также это .Вы, вероятно, также должны быть уверены, что буферизация не произойдет где-то еще.

РЕДАКТИРОВАТЬ: ОП опубликовал сообщение о замене для на , тогда как решило проблему

Я думаю, что теперь понимаю.while получает каждую строку и запускает цикл, тогда как for действует как foreach, а first получает все строки (требуется контекст списка), а затем зацикливает строки.

2 голосов
/ 24 мая 2010

Нашел это.Проблема с оператором for.

Следующий код работает как положено

open( PIPE, '-|', 'ant' ); 
while( <PIPE> ) {           # replacing 'for' with 'while'
    print; 
} 

Я не знаю причину, но теперь он работает.

...