use strict;
use warnings;
use Tie::File;
my $file = shift or die "usage: $0 file\n";
tie my @lines, 'Tie::File', $file or die "error: $!";
print $lines[$#lines]; # this is the last line in the file
Update: If you only require read access to the file, it is more correct to tie the file read-only like so:
use Fcntl 'O_RDONLY'; # add this line
# ... as before, then change the tie line as shown below
tie my @lines, 'Tie::File', $file, mode => O_RDONLY or die "error: $!"
+;
# ... as before
| [reply] [d/l] [select] |
You're opening a file twice, that may not be necessary if you reconstruct your code to use the eof function to detect the end of the file, there is a difference between eof and eof() however and the later will only detect the end of the last file in a list of files provided whereas eof -without the parentheses- can detect the end of each file ...
use strict;
use warnings;
while(<DATA>){
if(eof){ #Check if the last line has ' last '
print ~/\slast\s/ ? 'yes' : 'no';
}
}
__DATA__
one line
two lines
three lines
this is the last one
Excellence is an Endeavor of Persistence.
A Year-Old Monk :D .
| [reply] [d/l] [select] |
For what value of 'best'? There are many ways that you could find the last line of a file. A good solution for one context may be bad in a different context. What are the interesting constraints for your application? For example:
- Do you know the maximum line length?
- Are the lines all the same length?
- Is the new line character consistent within the file
- Is the new line character consistent between files
- Is the file large (thousands of lines)?
- Does the task need to be performed many times a second?
- Does the code need to be written as baby Perl?
True laziness is hard work
| [reply] |
Its right you do not have to open file twice.
If the files are small... you can always place file contents in and array and use them.
open(FILE, "< nanotest.txt") || "can't open $file: $!";
my @arr = <FILE>;
my $last = $#arr+1; ## you can also use $. instead of $#arr
my $count;
foreach (@arr)
{
$count++;
if ($count == $last)
{
# Validate last line
}
}
| [reply] [d/l] |
I like eyepopslikeamosquito's way the best. Normally, I would build an index, but that can get tedious. You can build an index on the fly mentally by looking at $lines[$#lines]. That's the last line, but, now shifting into reverse, the next to last line would be $lines[$#lines-1] and so on until you get to the first line. For example, in this script there are 17 lines of the file being examined, so the first line would be $lines[$#lines-16], and the last line would be $lines[$#lines]. The script prints out the number of lines, the first line, and the last
line. Adjust for the first line accordingly:
#!/usr/bin/perl
use strict;
use warnings;
use Fcntl;
use Tie::File;
use File::CountLines qw(count_lines);
my $file = shift or die "usage: $0 file\n";
tie my @lines, 'Tie::File', $file, mode => O_RDONLY
or die "error: $!";
my $number_of_lines = count_lines($file);
print "Number of lines: $number_of_lines", "\n";
print $lines[$#lines-16], "\n";
print $lines[$#lines], "\n";
| [reply] [d/l] [select] |
use File::ReadBackwards;
my $file = "/path/to/myfile.txt";
my $bw = File::ReadBackwards->new($file)
or die "Cannot read $file - $!";
my $last_line = $bw->readline;
$bw->close;
| [reply] [d/l] |
One simple way is below. The below code will run very fast and will work with files too large to fit into memory at once. If you have special special performance requirements and/or if the files are humongous, then please explain further. Otherwise I would recommend going with something simple.
#!/usr/bin/perl -w
use strict;
my $file = "somefile";
open (FILE, '<', $file) or die "unable to open $file\n";
my $first_line = <FILE>;
my $last_line;
while(<FILE>){$last_line = $_;}
print "$first_line"; #do what you need with them here
print "$last_line";
| [reply] [d/l] |
Is there any best way to find the last line of the file?
Any way is a good way, but they can't all be best, so there is no "any best way" | [reply] |