Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

Detecting last line and blank line

by Anonymous Monk
on Nov 07, 2017 at 00:03 UTC ( #1202892=perlquestion: print w/replies, xml ) Need Help??
Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Say you are reading in some date line by line, is it possible to do an if command that that looks if it's the last line?

if ($data = Last line){ print "This is the last line\n"; }

And a similar if it's a blankline (containing 0 characters). But I feel that's more easy.

Replies are listed 'Best First'.
Re: Detecting last line and blank line
by davido (Archbishop) on Nov 07, 2017 at 01:04 UTC

    The eof operator is useful here.

    #!/usr/bin/env perl use strict; use warnings; my $fh = \*DATA; while(<$fh>) { chomp; print "<<<$_>>> is line $."; print ", and is the last line." if eof($fh); } continue { print ".\n"; } __DATA__ line 1 line 2 line 3

    This produces the following output:

    <<<line 1>>> is line 1. <<<line 2>>> is line 2. <<<line 3>>> is line 3, and is the last line.

    My purpose in copying \*DATA into $fh was just so that the remainder of my example could operate on a filehandle that is closer to what one might see in typical code.


    Dave

      Anonymous Monk: eof is indeed useful, and just to add two points to what davido wrote, there are two peculiarities when it is used in while (<>) loops, including the implicit ones from the -n and -p command line switches. First, eof with and without empty parentheses is different - from its docs:

      In a while (<>) loop, eof or eof(ARGV) can be used to detect the end of each file, whereas eof() will detect the end of the very last file only.

      Second, davido's code example uses the line counter $., which does not get reset for each file in a while (<>) loop. To do that, you need close ARGV explicitly, that is:

      while (<>) { # your code here } continue { close ARGV if eof; # Not eof()! }

      This is normally done in a continue block because that way, it will still be executed even if you use next inside the loop.

      As for blank lines, I like to use next unless /\S/; to skip lines that contain only whitespace. That doesn't exactly meet your "0 characters" requirement - as LanX said, use eq to compare the line to "" after chomp (or to "\n" before).

      Although you don't say why you need to detect blank lines and the last line, note that setting $/=""; means files will be read in "paragraph mode", that is, records will be separated by one or more blank lines.

Re: Detecting last line and blank line
by 1nickt (Prior) on Nov 07, 2017 at 00:40 UTC

    If you know the number of lines, e.g if you get an array on standard input, or passed to a subroutine:

    use strict; use warnings; use feature qw/ say /; chomp( my @lines = (<DATA>) ); my $num = @lines; my $count = 1; for my $line ( @lines ) { say "the last line is $line" if $num == $count++; } __DATA__ foo bar baz qux
    $ perl 1202892.pl the last line is qux

    If you don't know the number of lines, e.g. when reading a file that may be too large to slurp into memory all at once:

    use strict; use warnings; use feature qw/ say /; # setting up the demo use Path::Tiny; my $file = Path::Tiny->tempfile; $file->spew("$_\n") for ('a' .. 'm'); ####### my $last_line; open my $fh, '<', $file or die "Cannot open file: $!"; while ( my $line = <$fh> ) { chomp $line; $last_line = $line; } say "the last line is $last_line"; __END__
    $ perl 1202892-2.pl the last line is m

    Hope this helps!


    The way forward always starts with a minimal test.

      I figured it out, before I saw you answer!

      But thanks anyway ;-) !

      (Ended up doing something similar to your last code)

Re: Detecting last line and blank line
by LanX (Bishop) on Nov 07, 2017 at 01:14 UTC
    See eof for last line.

    An empty line means $line eq "" after chomp $line

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

Re: Detecting last line and blank line
by sundialsvc4 (Abbot) on Nov 08, 2017 at 03:01 UTC

    Speaking to this requirement in a more general way, many fundamental data-processing procedures (dating all the way back to Herman Hollerith’s punched cards, and to spinning magnetic tapes since then), rely on the notion of processing sorted input-streams.

    If you know that a particular input-stream is sorted in some particular way, then you necessarily know that all records having any particular key-value must be consecutive.   Therefore, you can simply remember the values that you saw in the one and only-one ‘preceding record,’ and compare it to the record that you have now.   If the values of the key field(s) are not the same, then you know that you have just encountered the last occurrence of the previous key, and the first occurrence of the new one.   (“End-of-File” is simply a special-case of this.)

    Even today, many decades after the days of punched cards and magnetic tapes, the efficiencies of “sorted files” remain relevant.   (After all, Dr. Knuth entitled one of his books, Sorting And Searching.)   The one-time cost of sorting an input file ... which is likely to be much less “costly” than you might suppose ... can sometimes produce dramatic (as in, “orders of magnitude faster”) improvements in down-stream processing stages that are able to exploit (and, require) this fact.

      artificial intelligence troll bot?

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1202892]
Approved by beech
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2017-12-11 23:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What programming language do you hate the most?




















    Results (319 votes). Check out past polls.

    Notices?