如何获得Perl管道的输出?

时间:2010-05-23 20:44:32

标签: perl pipe

以下代码工作正常:

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

然而,它没有做我想要的。由于Ant构建可能需要5分钟,我希望逐行看到输出。 相反,我在整个过程结束时得到了整个输入。

使用Perl调试器查看它,Perl等待'for'语句,直到Ant终止。那是为什么?

3 个答案:

答案 0 :(得分:8)

只是为了完整性(问题在Uri的回答评论中得到解决)问题出现了,因为for表达式评估列表上下文中的<>运算符(see),等效于以下内容:

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

在列表上下文中,<>运算符尝试从其输入读取所有行以指向列表 - 并且输入来自进程,它将阻塞直到进程结束。只有在它之后它才会进入循环体。

替代语法

while( <PIPE> ) {           
    print; 
} 

等同于

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

,即它在每次循环迭代中消耗输入中的每一行,这就是在这种情况下想要做的事情。

答案 1 :(得分:3)

我认为问题在于缓冲。您可以像这样使文件句柄 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 中读到了类似的内容。另见this。您可能还应该确保缓冲不会发生在其他地方。

编辑:OP发布用替换 解决问题

我想我现在明白了。 while获取每一行并运行循环,而for的行为类似于foreach首先获取所有行(它需要列表上下文)和然后循环遍布。

答案 2 :(得分:2)

找到它。 问题在于'for'语句。

以下代码按预期工作

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

我不知道原因,但现在它正在发挥作用。