Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl - reading a file line by line in reverse order [duplicate]

Tags:

perl

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.

like image 616
powerboy Avatar asked Jul 10 '10 22:07

powerboy


2 Answers

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
like image 126
Greg Bacon Avatar answered Nov 15 '22 08:11

Greg Bacon


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->() );
like image 38
FMc Avatar answered Nov 15 '22 07:11

FMc