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

When I try this, looking for an empty line at the top of a file:
my $counter; print"TOP\n"; while( (<>) && counter <10){ $counter++; print"$_\n"; } print "BOTTOM";
it prints prints empty newlines for every line in the file (presumably after printing the ten lines I want).

Replies are listed 'Best First'.
Re: peeling the top 10 lines from a file
by reasonablekeith (Deacon) on May 16, 2005 at 15:24 UTC
    try ...
    use strict;
    and you'll see that you're missing a $ somewhere
    ---
    my name's not Keith, and I'm not reasonable.
Re: peeling the top 10 lines from a file
by holli (Abbot) on May 16, 2005 at 15:32 UTC
    You are missing the sigil at "counter <10". You would have spotted this if you used strict;
    use strict; my $counter=0; print"TOP\n"; while( $counter++<10) { last if eof(STDIN); $_=<>; print "$counter $_"; } print "BOTTOM";
    Update:

    More caveats:
    The second part of your conditional will never be checked because the first part is always true, unless the end of the file is reached.
    Furthermore it seems the <> does not assign the read line to $_ when there is a && afterwards.
    I don't know why. Anyone can explain that?

    Update: Silliness striked. Thanks Roy_Johnson.


    holli, /regexed monk/

      The problem with his while( (<>) && $counter < 10 ) {... (besides the fact that he's missing a sigil) is apparent when you turn on warnings and look at the output. Once you add the logical short circuit, the magic while(<>) is lost, and you end up with a plain old boolean evaluation of the <> operator. That results in two problems.

      First, $_ doesn't receive the current line of the file without explicitly assigning it. Try it with warnings and you'll see "Uninitialized value....." warnings for each line. Second, as the warnings also state, "Value of handle construct can be "0", test with defined()."


      Dave

      Perlnut says that $_ is only populated when a line-input operator is the sole critereon of the while test.

      which reads as, like it or lump it. :-)

      Update: Perlnut being my own personal shortcut for "Perl in a Nutshell".

      ---
      my name's not Keith, and I'm not reasonable.
Re: peeling the top 10 lines from a file
by davidrw (Prior) on May 16, 2005 at 15:35 UTC
    See above for fixing a syntax error. As for your empty newlines, it is because $_ includes the newline (i'm assuming $/ is \n) from the input file, so that is getting printed along with the one you put in your print statement.

    Also take a look at $. in the perlvar man page, which may be of interest to you. It's the current input record number, which you can use instead of having $counter (same functionality--just eliminates an extra variable).
    while( <> ){ print; # bail if past 10 lines # or if we hit a blank line last if $. >= 10 || $_ eq "\n"; }
      holli slaps his forehead

      I always forget about $.. This must be one of my blind spots.


      holli, /regexed monk/
        The only advice I can give you is in my sig.

        The Eightfold Path: 'use warnings;', 'use strict;', 'use diagnostics;', perltidy, CGI or CGI::Simple, try the CPAN first, big modules and small scripts, test first.

      Why are you bailing on blank lines? That wasn't specified in the OP, unless I'm missing something. Which is entirely possible, given my current caffeine level (low).
        I wasn't at first, then I re-read OP which said "looking for an empty line at the top of a file", and made me re-consider and add it in. I still don't know if bailing on blank lines is what the OP really needs/or wants, but from that quote i think it's possible so i figured i'd just throw it in and comment it and let OP go from there...

        Maybe i read too far into it -- none of the other responsers intrepeted it that way, but maybe they were going just off of the sample code...
Re: peeling the top 10 lines from a file
by davido (Cardinal) on May 16, 2005 at 15:41 UTC

    $counter is mis-typed within your while expression. It's missing its '$' sigil. Also, I think that some of the magic of while(<>) is lost when you put other criteria within the while() criteria.

    You could do it like this...

    print "TOP\n"; while( <> ) { last if $. > 10; # $. is the current line number within the file. print "$_\n"; } print "BOTTOM\n";

    Dave

Re: peeling the top 10 lines from a file
by sh1tn (Priest) on May 16, 2005 at 16:55 UTC
    #UNIX head: #head -10 'filename' #Perl equivalent: #perl -pe '$.>10&&exit' 'filename'


      I was going to point out head if nobody else had. Having "grown up" on Windows systems, it took me a while to figure out how many useful tools a UNIX system provides. You don't always need the Perl Swiss Army Knife if the right size screwdriver is just lying around already.

      To check for empty lines (as the original post suggests), you can count them using grep:
      head -10 filename | grep -c '^$'
Re: peeling the top 10 lines from a file
by blazar (Canon) on May 17, 2005 at 09:23 UTC
    while( (<>) && counter <10){
    Setting aside all the other matters already addressed by other posters, AFAIK while's magic with angular parentheses holds only for the
    while(<>) { # ...
    construct (or the equivalent one including an explicit filehandle).

    Update: (to better explain myself) hence your script, even if corrected from the obvious error, would give you a "Use of uninitialized value in print" warning.

    Also, unless you chomp it shouldn't be necessary to include "\n" in your output string. Unless you really want double spacing. In any case I'd probably locally set $\ suitably instead.

    Hence all in all I'd simply do:

    while (<>) { print; last if $. == 10; }