Reputation: 43
I am trying to create a Perl script that outputs the last two lines of a file. My current script accomplishes what I want, except that it reads the first two lines rather than the last two.
use strict;
use warnings;
my $file = 'test.txt';
open my $info, $file or die "Could not open $file: $!";
while( my $line = <$info>) {
print $line;
last if $. == 2;
}
close $info;
What must I alter so that the script reads the last two lines rather than the first two?
Upvotes: 4
Views: 812
Reputation: 239652
This is harder than printing the first lines! Here are a few options, ranging from least to most clever:
tail
Because who actually needs a perl script to print the last two lines of a file?
print do {
open my $info, $file or die ...;
(<$info>)[-2, -1];
};
open my $info, $file or die ...;
my @lines;
while (my $line = <$info>) {
shift @lines if @lines == 2;
push @lines, $line;
}
print @lines;
This is the most memory efficient, especially if a "line" is worryingly long, but complicated. However, there's a module for it: File::ReadBackwards. It lets you do:
use File::ReadBackwards;
my $info = File::ReadBackwards->new($file) or die ...;
my $last = $info->readline;
my $second_last = $info->readline;
print $second_last, $last;
Upvotes: 15
Reputation: 126722
You can use Tie::File
or File::ReadBackwards
.
The code looks like this.
Using Tie::File
use strict;
use warnings;
use Tie::File;
my $file = 'test.txt';
tie my @file, 'Tie::File', $file or die $!;
print "\nUsing Tie::File\n";
print "$_\n" for @file[-2,-1];
Using File::Readbackwards
use strict;
use warnings;
use File::Readbackwards;
my $file = 'test.txt';
my $backwards = File::ReadBackwards->new($file) or die $!;
my @last_two;
while (defined(my $line = $backwards->readline)) {
unshift @last_two, $line;
last if @last_two >= 2;
}
print "\nUsing File::ReadBackwards\n";
print @last_two;
Upvotes: 1