Shell – How to make two commands consume input from stdin sequentially

shell

The following perl script consume-10-lines-and-exit reads ten lines from stdin and prints them. After that it exits.

#!/usr/bin/env perl
use strict;
use warnings FATAL => 'all';

for (my $i = 0; $i < 10; $i++) {
    my $line = <STDIN>;
    print $line;
}

I'm trying to combine consume-10-lines-and-exit and cat in such a way that the first ten lines of input and consumed and printed by the first command and then the rest are consumed by cat.

The following code few snippets all print 1 through 10 instead of 1 through 13 like I was expecting.

printf '1 2 3 4 5 6 7 8 9 10 11 12 13' \
    | tr ' ' '\n' | { perl consume-10-lines-and-exit; cat; }

printf '1 2 3 4 5 6 7 8 9 10 11 12 13' \
    | tr ' ' '\n' | ( perl consume-10-lines-and-exit; cat )

printf '1 2 3 4 5 6 7 8 9 10 11 12 13' \
    | tr ' ' '\n' | sh -c 'perl consume-10-lines-and-exit; cat'

Is there a construction for sequencing commands so they will read input from stdin until they exit and then the next command will continue where the previous one left off?

Best Answer

Your problem is that perl is using buffered input, so reads ahead beyond the lines you want to consume. Try this byte-by-byte version:

perl -e '
use strict;
use warnings FATAL => "all";
for (my $i = 0; $i < 10; $i++) {
  my $line;
  while(sysread(*STDIN,my $char,1)==1){
      $line .= $char;
      last if $char eq "\n";
  }
  print $line;
}'
Related Question