7

Possible Duplicate:
How can I read lines from the end of file in Perl?

First read the last line, and then the last but one, etc. The file is too big to fit into memory.

Community
  • 1
  • 1
powerboy
  • 10,523
  • 20
  • 63
  • 93

3 Answers3

8

Reading lines in reverse order:

use File::ReadBackwards;

my $back = File::ReadBackwards->new(shift @ARGV) or die $!;
print while defined( $_ = $back->readline );

I misread the question initially and thought you wanted to read backward and forward, in alternating fashion -- which seems more interesting. :)

use strict;
use warnings;
use File::ReadBackwards ;

sub read_forward_and_backward {
    # Takes a file name and a true/false value.
    # If true, the first line returned will be from end of file.
    my ($file_name, $read_from_tail) = @_;

    # Get our file handles.
    my $back = File::ReadBackwards->new($file_name) or die $!;
    open my $forw, '<', $file_name or die $!;

    # Return an iterator.
    my $line;    
    return sub {
        return if $back->tell <= tell($forw);
        $line = $read_from_tail ? $back->readline : <$forw>;
        $read_from_tail = not $read_from_tail;
        return $line;
    }

}

# Usage.    
my $iter = read_forward_and_backward(@ARGV);
print while defined( $_ = $iter->() );
Gray
  • 115,027
  • 24
  • 293
  • 354
FMc
  • 41,963
  • 13
  • 79
  • 132
8

Simple if tac is available:

#! /usr/bin/perl

use warnings;
no warnings 'exec';
use strict;

open my $fh, "-|", "tac", @ARGV
  or die "$0: spawn tac failed: $!";

print while <$fh>;

Run on itself:

$ ./readrev readrev
print while <$fh>;

  or die "$0: spawn tac failed: $!";
open my $fh, "-|", "tac", @ARGV

use strict;
no warnings 'exec';
use warnings;

#! /usr/bin/perl
Greg Bacon
  • 134,834
  • 32
  • 188
  • 245
  • Do you know how to use this solution when the file is utf8 encoded? – W3Coder Aug 11 '15 at 16:39
  • Figured it out myself - in case others need to know: ... use Encode; ... binmode STDOUT, ':utf8'; ... print decode_utf8 ($_) ... – W3Coder Aug 12 '15 at 06:30
3

I've used PerlIO::reverse for doing this recently. I prefer the IO layer of PerlIO::reverse over the custom object or tied handle interface offered by File::ReadBackwards.

danboo
  • 173
  • 1
  • 5