How to get out of the Perl channel as it appears?

The following code works in order:

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

However, he does not do what I want. Since Ant builds can take 5 minutes, I would like to see the output line by line. Instead, I get all the input at the end of the process.

By looking at it with the Perl debugger, Perl waits for the 'for' statement until Ant completes. Why is this?

+7
perl pipe
source share
3 answers

Just for completeness (the problem was solved, as indicated in the comment to Uri's answer), the problem arose because of the for expression, which evaluates the <> operator in the context of the list ( see ), which is equivalent to the following:

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

In the context of the list, the <> operator tries to read all the lines from its input to asign in the list - and the input comes from the process, it will be blocked until the process ends. Only after that he will enter the body of the cycle.

Alternative syntax

 while( <PIPE> ) { print; } 

equivalent instead

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

ie, it consumes every line from the input in each iteration of the loop, and this is what you want to do in this scenario.

+8
source share

I believe the problem is buffering. You can make the file descriptor hot (unbuffered) as follows:

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

This should disable buffering for PIPE. I read about something similar in Learning Perl, 5th. See this . You should probably also make sure that buffering is not happening anywhere else.

EDIT: OP posted that replacing for to solve the problem

I think now I understand. while gets each line and starts the loop, while for acts like foreach and first gets all the lines (needs a list context) and then iterates over the lines.

+3
source share

Found. The problem is the expression for.

The following code works as expected

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

I do not know the reason, but now it works.

+2
source share

All Articles