2010-05-23 65 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