On Mon, 28 Oct 2002 13:54:28 -0500, [EMAIL PROTECTED] (Nikola
Janceski) wrote:

>without using 'tail' how can I get the trailing 5 lines of a large file
>quickly, without loading it all to memory?
>
>is there anyway without pop and shifting through an array foreach line? (<=
>this is the only way I could think of doing it)

Here is a method that I've used. The idea is to grab a chunk off the
end of the file, then load that into an array and print the last
"number" of elements.
It rely's on you assuming the line length, in order to compute the
chunk size. In the example, I've chosen a 400 character line, which
takes almost all files into account. It might waste a little memory,
but it's pretty fast on big files.
#######################################################
#!/usr/bin/perl -w
# example for files with max line lengths < 400, but it's adjustable
# usage tailz  filename  numberoflines
use strict;

die "Usage: $0 file numlines\n" unless @ARGV == 2;
my ($filename, $numlines) = @ARGV;

my $chunk = 400 * $numlines; #assume a <= 400 char line(generous)
                                
# Open the file in read mode
open FILE, "<$filename" or die "Couldn't open $filename: $!";
my $filesize = -s FILE;
if($chunk >= $filesize){$chunk = $filesize}
seek FILE,-$chunk,2; #get last chunk of bytes

my @tail = <FILE>;
if($numlines >= $#tail +1){$numlines = $#tail +1}
splice @tail, 0, @tail - $numlines;

print "@tail\n";
exit;
######################################################

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

Another method, which is slow,
is to go to the end of the file, and count
back the number of newlines.
#############################################################
#!/usr/bin/perl -w
# linux only, 
# usage tailz  filename  numberoflines
use strict;

my $filename = shift or die "Usage: $0 file numlines\n";
my $numlines  = shift;
my $byte;     

# Open the file in read mode
open FILE, "<$filename" or die "Couldn't open $filename: $!";

# Rewind from the end of the file until count eol's
seek FILE,-1, 2;  #get past last eol
my $count=0;
 while (1){
   seek FILE,-1,1;
   read FILE,$byte,1;
   if(ord($byte) == 10 ){$count++;if($count == $numlines){last}}
   seek FILE,-1,1;
 if (tell FILE == 0){last}  
}
$/=undef;
my $tail = <FILE>;
print "$tail\n";
exit;
##################################################################


-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to