http://www.perlmonks.org?node_id=117846

airblaine has asked for the wisdom of the Perl Monks concerning the following question:

I have multiple txt files in a directory. I need to extract the first four lines of each file and output/appened it with the file name to another file. This should be easy, right? I can do it on one line, I can do it with a search string, but I can't find how to just pull four lines out! Argghhh... Thank You in advance...

Replies are listed 'Best First'.
Re: Extract lines and output...
by jeroenes (Priest) on Oct 10, 2001 at 00:09 UTC
    There are so many ways to do this. Maybe straightforward, don't print until $. is 4 (see perlvar):
    while(<>){ next if $. <4; #codeblockdoingsomeotherthings print; }

    HTH,

    Jeroen

    Update: I couldn't resist adding some more possibilities:

    #1 slurping the whole thing in memory, and splice @file = <>; splice @file, 0, 4; print @file; #2 using the flip-flop operator while (<>){ next unless $.>3 .. 1; #... print; } #3 another flip-flop $start = -3; while (<>){ next unless $start++ .. 1; #.... print; } #4 just repeat 4 times $dummy=<> for 1..4; #5 make it multifile proof while (<>){ close( ARGV) if (eof);  next unless $.>3 .. eof; #... print; }
Re: Extract lines and output...
by Fletch (Bishop) on Oct 10, 2001 at 00:57 UTC
    foreach( @files ) { my $outfile = outfile_name( $_ ); open( CUR, $_ ) or die "open $_: $!\n"; open( OUT, ">$outfile" ) or die "open $outfile: $!\n"; print OUT $_, "\n"; while( <CUR> ) { last if $. > 4; print OUT; } close( OUT ); close( CUR ); } sub outfile_name { my $base = shift; return $base . "_distilled" }
      Hi Fletch,

      I liked your approach. I'm not sure you need the sub in it
      though; you're already doing variable interpolation when you
      open( OUT, ">$outfile" ) or die ... so you could lean it up a bit:
      open( OUT, ">${_}_distilled" ) or die ...

      Here's what your code inspired me to do

      #!/usr/bin/perl for(glob '*') { /^$0$/ and next; # don't process the script open(I,"<$_") or die("$_: $!"); open(O,">$_.$$") or die("$_: $!"); print O $_,"\n"; { $. > 4 ? last : print O while(<I>); } close(I); } exit;

      While writing and subsequently edting above program I discov-
      ered the redundancy of local() in certain contexts. I originally wrote
      { local $_ = undef; $. > 4 ? last : print O while(<I>) }
      RRedundancy bad, so local went away.

      Update: changed >$outfile_distilled
      to ${_}_distilled which actually makes sense
      in the context of the original program.

      blyman

        If you like brief you might like this:
        #!/usr/bin/perl -w while(<*>) { next if /^$0$/; open I, $_ or die "$_: $!"; open O,">$_.bak" or die "$_.bak: $!"; print O $_, "\n", (<I>)[0..3]; close I, close O; }

        cheers

        tachyon

        s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Re: Extract lines and output...
by cjensen (Sexton) on Oct 10, 2001 at 01:45 UTC
    I usually use the unix command-line for stuff like this:

    head -4 *.txt | \
    perl -pe '/==>\s(.*)\s<==/ ? ($f, $_) = ($1, undef) : $_ = "$f: $_";' \
    >> output_filename
      Perfect! Thanks all! A big help and learned alot! Perl rules!