Last 100 lines in a file

Yesterday, I had to pick out the last 100 lines in a file, for a small log viewer I was writing. Neither the Perl FAQ nor the Perl Cookbook had quite the right answer. So, this is what I ended up with.

sub last_lines {
  my ( $fh, $howmany ) = @_;
  my ( @lines, $i );
  while ( <$fh> ) {
    chomp;
    $lines[ $i++ ] = $_;
    $i = 0 if $i == $howmany;
  }
  return grep { defined }
    @lines[ $i .. $howmany - 1 ], @lines[ 0 .. $i - 1 ];
}

This is reasonably memory efficient, more so than the example I found which read the entire file in and then just picked the last $howmany items from the array.

The last line is interesting. We have to “swivel” the array around a partition point, in order to get the entries into the correct order. Also, we have to get rid of undefined entries. These crop up if you have less than $howmany lines in the file.

Comments 4

  1. Aristotle Pagaltzis wrote:

    Engh. View source on the page for the formatting. You get the idea.

    Posted 20 Jan 2006 at 00:09
  2. Aristotle Pagaltzis wrote:

    Errk, how convoluted.

    <code>
    sub last_lines {
    my ( $fh, $howmany ) = @_;
    my @lines;
    while ( <$fh> ) {
    chomp;
    push @lines, $_;
    shift @lines if @lines > $howmany;
    }
    return @lines;
    }
    </code>

    Posted 20 Jan 2006 at 00:12
  3. Aristotle Pagaltzis wrote:

    Also, a lengthy treatise on this issue:

    http://www.perlmonks.org/index.pl?node_id=162034

    Posted 21 Jan 2006 at 00:33
  4. Dominic Mitchell wrote:

    Thanks, Aristotle, that’s a much better idea! I’ve started doing that instead now.

    BTW, the comment formatting should be using textile

    Posted 25 Jan 2006 at 01:38