Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
PerlMonks  

Find last line in Text file parsing

by selva (Scribe)
on Oct 04, 2010 at 05:25 UTC ( #863257=perlquestion: print w/ replies, xml ) Need Help??
selva has asked for the wisdom of the Perl Monks concerning the following question:

Dear Wise Monks,

I'm trying to parse and validate text file content. For the first line and last line alone validation will be different.

I am using following code to find the last line of the file.

open(FILE, "< $file") or die "can't open $file: $!"; $count++ while <FILE>; # $count now holds the number of lines read open(FILE, "< $file") or die "can't open $file: $!"; for ($i=0; <FILE>; $i++) { if ($i == $count) { # Validate last line } }

Is there any best way to find the last line of the file?

Comment on Find last line in Text file parsing
Download Code
Re: Find last line in Text file parsing
by eyepopslikeamosquito (Canon) on Oct 04, 2010 at 05:31 UTC

    Perhaps use the core Tie::File module:

    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

Re: Find last line in Text file parsing
by biohisham (Priest) on Oct 04, 2010 at 06:21 UTC
    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 .
Re: Find last line in Text file parsing
by vsailas (Beadle) on Oct 04, 2010 at 06:42 UTC

    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 } }
Re: Find last line in Text file parsing
by Anonymous Monk on Oct 04, 2010 at 06:49 UTC
    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"

Re: Find last line in Text file parsing
by Khen1950fx (Canon) on Oct 04, 2010 at 07:46 UTC
    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";
Re: Find last line in Text file parsing
by GrandFather (Cardinal) on Oct 04, 2010 at 08:10 UTC

    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:

    1. Do you know the maximum line length?
    2. Are the lines all the same length?
    3. Is the new line character consistent within the file
    4. Is the new line character consistent between files
    5. Is the file large (thousands of lines)?
    6. Does the task need to be performed many times a second?
    7. Does the code need to be written as baby Perl?
    True laziness is hard work
Re: Find last line in Text file parsing
by Marshall (Prior) on Oct 04, 2010 at 18:24 UTC
    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";
Re: Find last line in Text file parsing
by repellent (Priest) on Oct 04, 2010 at 23:09 UTC
    See File::ReadBackwards.
    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;

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://863257]
Approved by biohisham
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (15)
As of 2014-10-31 15:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (219 votes), past polls