Как я получаю вывод от канала Perl, поскольку это становится доступным?

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

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

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

Смотря на него с отладчиком Perl, Perl ожидает в оператора, пока Муравей не завершается. Почему это?

7
задан brian d foy 23 May 2010 в 22:10
поделиться

3 ответа

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

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

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

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

while( <PIPE> ) {           
    print; 
} 

вместо этого эквивалентен

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

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

8
ответ дан 6 December 2019 в 19:33
поделиться

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

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 получает все строки (ему нужен контекст списка) и , затем перебирает строки.

3
ответ дан 6 December 2019 в 19:33
поделиться

Нашел. Проблема в выражении «for».

Следующий код работает, как ожидалось

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

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

2
ответ дан 6 December 2019 в 19:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: