开发者

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

开发者 https://www.devze.com 2022-12-31 14:25 出处:网络
The following code is working sort of fine: open( PIPE, \'-|\', \'ant\' ); for( <PIPE> ) { print; }

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. 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. 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:

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;
}

i.e., it consumes each line from the input in each loop iteration, and this is what one wants to do in this scenario.


Found it. The problem is with the 'for' statement.

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.


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. I read about something like this in 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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消