Answering my own question...

scalar(<STDIN>) didn't work, but thanks for the suggestion, it lead me to the 
solution.

Assaf Gordon wrote, On 12/15/2010 03:05 PM:
> My goal is to have a tiny perl program, that reads STDIN, grabs
> couple of lines from it, then executes another program which should
> consume the rest of the lines from STDIN.
> 
> This works as expected when using shell redirection, but not when
> using pipes.
> 
With 'strace', I found that perl slurps a lot of input from STDIN (more than 
one line), then use lseek to reposition in STDIN to point right at the second 
line.

When STDIN is a file (with redirection), it works:
7852  read(0, "A\nB\nC\nD\nE\n", 4096)  = 10
7852  lseek(0, 2, SEEK_SET)             = 2
7852  lseek(0, 0, SEEK_CUR)             = 2

When STDIN is a pipe, it obviously doesn't work:
7672  read(0, "A\nB\nC\nD\nE\n", 4096)  = 10
7672  lseek(0, 2, SEEK_SET)             = -1 ESPIPE (Illegal seek)

And so by the time "sort" is executed, data from STDIN is already consumed ;(

The solution I've found is to bypass perlio and use sysread one char at the 
time:
==========
#!/usr/bin/perl
use strict;
use warnings;

sub read_line_non_buffered()
{
        my $line = '';
        while ( 1 ) {
                my $c;
                my $rc = sysread STDIN, $c, 1;
                die "Read error: $!" unless defined $rc;
                return $line if $rc==0 && $line;
                return undef if $rc==0 && (!$line);
                $line .= $c ;
                return $line if ( $c eq "\n");
        }
}

my $dummy = read_line_non_buffered();
system("sort -r");
==========

If you have better solution (or comments on my solution), I'm happy to hear.

Thanks,
 -Assaf.

_______________________________________________
Perl mailing list
Perl@perl.org.il
http://mail.perl.org.il/mailman/listinfo/perl

Reply via email to