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

Hi. I am still very new to perl. I bought a Visual Quickstart Guide to Perl and CGI and now I have been told that it sucks. Can anyone recommend a good book for someone who is serious about web based programming with perl? Also, I am trying to do something that is probably very simple. I know how to do this with something simple like Visual Basic, but I do not know the perl commands well enough yet. I am trying to add a sub routine to an existing script that will open users.dat, read how many lines there are in the script and then put that value into a variable (to be displayed as "X" users to date). Is there an EOF command in Perl, can anyone help? Thanks!

Replies are listed 'Best First'.
Re: Count number of lines?
by Albannach (Monsignor) on Jun 20, 2001 at 06:41 UTC
    Here are a couple of ways the Monastery can help you in your Perl quest:
    • The Search box at the top left of your screen is great for looking up keywords. Just type eof there, hit enter and see what turns up.
    • The Q&A link at the top of every page here will take you to a wonderful selection of common solutions, one of which (under the QandASection: files topic) is titled: How do I find the total number of lines in a file? which should provide you with some good reading.

    --
    I'd like to be able to assign to an luser

Re: Count number of lines?
by bikeNomad (Priest) on Jun 20, 2001 at 06:30 UTC
    To count the number of lines in your file:

    my $lines = 0; open USERDAT, 'users.dat' or die "can't open users.dat: $!\n"; $lines++ while (<USERDAT>); close USERDAT; # now lines has the number of lines.
Re: Count number of lines?
by Zaxo (Archbishop) on Jun 20, 2001 at 06:57 UTC

    This is actually Not Good Code, but one liners from the prompt are good for getting girls

    $ perl -e 'open FH,"users.dat";print scalar(map {1} <FH>)," users to d +ate\n"' 653 users to date $

    Properly, the open should be checked and the file closed.

    After Compline,
    Zaxo

      I believe Abigail scored the ultimate Perl one-liner to count lines in a file, with (modified to fit the current context)...

        perl -lpe '}{$_="$. users to date"' users.dat

      A little more readable is ...

        perl -lne 'END { print "$. users to date" }' users.dat

          --k.


        For those of you who wondered, as I did, here's what perl -lpe '}{$_="$.users to date"' is doing:

        The -p option wraps your code in the following loop (see perlrun):

        LINE:
          while (<>) {
            ...             # your program goes here
          } continue {
            print or die "-p destination: $!\n";
          }
        

        The code supplied with the -e switch inserts a closing curly brace, creating an empty while BLOCK, followed by an opening curly brace, which makes a bare block after the while block.

        LINE:
          while (<>) { }
          { $_="$. users to date" }
          continue {
            print or die "-p destination: $!\n";
          }
        

        The while loop reads all the input records, the bare block assigns the string including the value of the input record counter to $_, and the continue block prints the string.

      On a large file, that could be a very expensive operation. I'd suggest (in terms of 1 liners)
      perl -ae '1 while <>;print $.' users.dat

      mr.nick ...

        update: I may have my indentation mixed up! I'd still like to know if yours is faster than abigail's though.

        how is this faster than the above? it looks like it's doing the same thing (while through the file and print $.). is there some sort of overhead with a continue block?

        also, is -a doing something special? I'm confused because perl --help says -a    autosplit mode with -n or -p (splits $_ into @F) which doesn't seem to apply here.

        "Argument is futile - you will be ignorralated!"

Re: Count number of lines?
by VSarkiss (Monsignor) on Jun 20, 2001 at 07:00 UTC
    Hello and welcome!

    I can't really comment on good books for CGI programming as I only do a little of it, but try "CGI Programming with Perl" by Guelich, Gundavaram, and Birznieks. I like it and find it useful. However, being new to Perl, you may want to start with the Camel book or "The Perl Cookbook" by Christiansen and Torkington. All are O'Reilly books.

    It sounds like you're asking how to "think Perl". That may take a while, but it sounds like you're going in the right direction: modify existing code. Here's how I might code the routine you're referring to:

    sub how_many_lines { open I, 'users.dat' or warn("Couldn't open users.dat\n"), return; # That single statment will try to open "users.dat" # (it better be in the current directory). If that # fails, it'll print "Couldn't open users.dat" and # return undef (the undefined value) to the calling # routine. Yes, it's very terse, but that's part of # the power of Perl. my $lines; # Declare $lines local to this scope (the sub) ++$lines while <I>; # Read the entire file a line at a time, incrementing $lines # every time. close I; # Close the file handle $lines; # return the count to the caller. }
    To answer your specific question, yes, there is an EOF test in Perl, but it's very rarely useful. The <> operator returns the undefined value at end-of-file, so an explicit test is usually redundant.

    HTH, and good luck on your journey.

      After the "open I, 'users.dat' or warn..." line, would this line flock the file?: flock I, 2; Thanks. slcpub@yahoo.ca
        Yes. I is a filehandle here, and can be used as the first argument to flock, as well as others like seek.

        BTW, to avoid having to remember that 2 is "exclusive lock", you can use symbolic names from the Fcntl module:

        use Fcntl; ... flock(I, LOCK_EX);
        See the perlfunc document for details.
Re: Count number of lines?
by lemming (Priest) on Jun 20, 2001 at 07:43 UTC
Re: Count number of lines?
by CheeseLord (Deacon) on Jun 20, 2001 at 06:44 UTC

    Well, I'm not exactly one to ask about Perl and CGI (as I haven't done very much of it), but if you've got Perl down reasonably well, I'd suggest looking at "CGI Programming with Perl" from O'Reilly. It helped me out a good deal with the little I've done. If you're still working with Perl, I'd recommend getting that down first -- in which case, there's always the Camel (and/or Llama) book.

    And about your number of lines question:

    sub numlines { my $file = shift @_; unless (open FILE, "$file") { warn "Could not open $file: $!\n"; return -1; # Only a recommendation } my @lines = <FILE>; close FILE; return scalar @lines; }

    I don't know if there's a way to determine the number of lines in a file without reading the entire thing... you might also want to look up perlvar and check out $., as that likely has the "cooler" way to accomplish that task. Hope that helps!

    His Royal Cheeziness