简体   繁体   English

如何获得Perl管道的输出?

[英]How do I get the output from a Perl pipe as it becomes available?

The following code is working sort of fine: 以下代码工作正常:

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

However, it doesn't do what I want. 但是,它没有做我想要的。 Since the Ant build can take 5 minutes, I would like to see the output line by line. 由于Ant构建可能需要5分钟,我希望逐行看到输出。 Instead, I'm getting the entire input at the end of the process. 相反,我在流程结束时获得了整个输入。

Looking at it with the Perl debugger, Perl waits at the 'for' statement, until Ant terminates. 使用Perl调试器查看它,Perl等待'for'语句,直到Ant终止。 Why is that? 这是为什么?

Just for completeness (problem was solved as pointed out in the comment to Uri's answer) the problem arose because the for expression evaluates the <> operator in list context ( see ), equivalently to the following: 只是为了完整性(问题在Uri的答案的评论中得到解决)问题出现了,因为for表达式评估列表上下文中的<>运算符( 请参阅参考资料 ),等效于以下内容:

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

In list context, the <> operator tries to read all lines from its input to asign to the list - and the input comes from a process, it will block until the process ends. 在列表上下文中, <>运算符尝试从其输入读取所有行以指向列表 - 并且输入来自进程,它将阻塞直到进程结束。 Only afterwards it it will enter the loop body. 只有在它之后它才会进入循环体。

The alternative syntax 替代语法

while( <PIPE> ) {           
    print; 
} 

is equivalent instead to 相当于

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

ie, it consumes each line from the input in each loop iteration, and this is what one wants to do in this scenario. 即,它在每次循环迭代中消耗来自输入的每一行,这是在这种情况下想要做的事情。

I believe the problem is buffering. 我相信问题在于缓冲。 You could make the filehandle hot (unbuffered) like so: 您可以将文件句柄设置为 (无缓冲),如下所示:

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

This should disable buffering for PIPE. 这应该禁用PIPE的缓冲。 I read about something like this in Learning Perl, 5TH . 我在Learning Perl,5TH中读过类似的内容。 See this , also. 也。 You should probably also make sure buffering doesn't happen someplace else. 您可能还应该确保缓冲不会发生在其他地方。

EDIT: the OP posted that replacing the for with while solved the problem 编辑:OP发布替换for for while解决了问题

I think I understand now. 我想我现在明白了。 while gets each line and runs the loop, whereas for acts like foreach and first gets all the lines (it needs list context) and then loops over the lines. while得到的每一行,并运行循环,而for像动作foreach第一得到所有的行(它需要列表上下文)中, 然后循环通过线路。

Found it. 找到了。 The problem is with the 'for' statement. 问题在于'for'语句。

The following code works as expected 以下代码按预期工作

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

I don't know the reason, but now it is working. 我不知道原因,但现在它正在发挥作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM