2010-05-23 83 views
7

下面的代碼工作之類的罰款:如何從Perl管道獲得輸出?

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

但是,它不會做我想做的。由於Ant構建可能需要5分鐘,我希望逐行看到輸出。 取而代之,我在整個過程結束時收到整個輸入。

用Perl調試器查看它,Perl等待'for'語句,直到Ant終止。這是爲什麼?

回答

8

只是爲了完整性(問題解決了在以烏里的答覆評論中指出)的問題出現,因爲for表達式的計算結果在列表環境中<>運營商(see),等同於以下內容:

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

在列表上下文中,<>操作員嘗試從其輸入讀取所有行以指派給列表 - 並且輸入來自進程,它將阻塞,直到進程結束。只有在之後它纔會進入循環體。

替代語法

while(<PIPE>) {   
    print; 
} 

相當於而是

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

即,它消耗在每次循環迭代輸入中的每行,這是一個想在這種情況下該怎麼辦。

3

我相信問題是緩衝。你可以做出這樣的文件句柄(無緩衝),所以:

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

這應該PIPE禁用緩衝。我在學習Perl,5TH。另請參閱this。你也應該確保緩衝不會發生在其他地方。

編輯:OP張貼與更換解決了這個問題

我想我現在明白了。 while獲取每一行並運行循環,而for作用就像foreach第一得到所有的行(它需要列表上下文)和然後環路上的行。

+7

緩衝可能是問題,但有問題的緩衝區在Ant方面,而不是Perl的方面。您只需要關閉輸出管道而不是輸入管道的緩衝。你需要找到一些方法告訴Ant不要緩存它的輸出。你無法解決Perl方面的問題。 – cjm 2010-05-23 21:00:18

2

找到它。 問題在於'for'語句。

下面的代碼按預期工作

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

我不知道原因,但現在它正在發揮作用。

+2

要理解原因,請參閱http://stackoverflow.com/questions/585341/ – Joe 2010-05-23 21:15:23

+0

如果您回答了自己的問題,最好編輯原始問題並添加答案,而不是發表回覆。 – 2010-05-23 22:42:45

+2

@Barry Brown發佈你自己的答案,並接受它,如果沒有人提供更好的答案被接受(heh)實踐SO。 http://meta.stackexchange.com/questions/12513/stackoverflow-should-i-answer-my-own-question-or-not – hobbs 2010-05-24 01:16:41