Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!!!
Would anyone know how to read the first and last line of any text file?
Thank you all!!!

Replies are listed 'Best First'.
Re: Reading Lines from Text file
by ikegami (Patriarch) on Feb 02, 2006 at 16:53 UTC
    my $first; my $last; { open(my $fh, '<', 'file') or die("Unable to open input file: $!\n"); while (<$fh>) { $first = $_ if not defined $first; $last = $_; } }

    or

    use File::ReadBackwards (); my $first; my $last; { open(my $fh, '<', 'file') or die("Unable to open input file: $!\n"); $first = <$fh>; } { my $fh = File::ReadBackwards->new('file') or die("Unable to open input file: $!\n"); $last = $fh->readline(); }

    or

    my $first; my $last; { open(my $fh, '<', 'file') or die("Unable to open input file: $!\n"); ($first, $last) = (<$fh>)[0, -1]; }
Re: Reading Lines from Text file
by malduarte (Initiate) on Feb 02, 2006 at 17:44 UTC
    This is a good example of a simple question which can have complex answers depending of the circumstances....
    1. Small files:
      perl -e "@l = <>; print 'first : ', $l[0], 'last : ', $l[$#l];" filen +ame
    2. This approach is only recommended for small files because all the lines are being read to an array (copying everything to memory before printing the lines)

    3. Medium sized files:
      perl -e "$first = <>; while($line = <>) { $last = $line; }; print 'fir +st : ', $first, 'last : ', $last;" filename
      This approach is recommended for medium sized files because it's reading one line at a time into memory.

      It's still not recommended for larges files because the entire file is being read. If you have a 4gbyte file and your I/O subsystem is only able to read 10 Mbytes/second you're going to take 400 seconds to get the answer.


    4. Really large files
      For really large files you can read the first line normally (see above). To read the last line, you have to:
      • seek to the end of the file
      • search for the line terminator of the line before the last
      • read from the position of the character after the line terminator to the end of file.

      Update: Use File::ReadBackwards . I didn't knew about this module and ended up reinventing the wheel (and ended up with a square wheel when compared with File::ReadBackwards :-)


    5. There's More Than Way To Do It,
      • seek to the end of the file
      • search for the line terminator of the line before the last
      • read from the position of the character after the line terminator to the end of file.
      Or use File::ReadBackwards as ikegami suggests.


      holli, /regexed monk/
Re: Reading Lines from Text file
by zshzn (Hermit) on Feb 02, 2006 at 18:18 UTC
    And then of course there is the lazy, unportable solution.
    my $first = `head -1 $filename`; my $second = `tail -1 $filename`;
    If you happened to want a solution regardless of the implementation (ie Perl or not), and were ignorant of the head and tail programs, then learn to use those.
      Why unportable? There are versions of "tail" and "head" for various OSses.


      holli, /regexed monk/
        Even if there are versions available for other OSses:
        • not every tail and head accept the same set of arguments
        • you may not have a compiler available to compile new tools
        • you may not able to install new software on the machine you're working,
        • Since you're using backticks, you're relying on whatever shell you have available, environment variables, aliases, (...)
        The safest way is to rely only on the Perl interpreter.
      Or, if you don't mind a little less portability in order to do one less sub-shell invocation:
      my ( $first, $last ) = `head -1 $filename && tail -1 $filename`;
Re: Reading Lines from Text file
by Corion (Patriarch) on Feb 02, 2006 at 16:31 UTC

    I guess the secret to it is in skipping the things in the middle.

    1. Read lines
    2. ...
    3. Profit!
      Or the George Costanza approach...

      1. Open the file
      2. yadda yadda yadda
      3. First and last line.

                      - Ant
                      - Some of my best work - (1 2 3)

        "You yadda'd the best part!"

        "No, I told you about opening the file."

        *Cue scene change bass riff*