Book HomeLearning Perl, 3rd EditionSearch this book

A.15. Answers to Chapter 16 Exercises

  1. Here's one way to do it:

    open PF, '/path/to/perlfunc.pod' or die "Can't open perlfunc.pod: $!";
    dbmopen my %DB, "pf_data", 0644 or die "Can't create dbm file: $!";
    
    %DB = ( );  # wipe existing data, if any
    
    while (<PF>) {
      if (/^=item\s+([a-z_]\w*)/i) {
        $DB{$1} = $DB{$1} || $.;
      }
    }
    
    print "Done!\n";

    This one is similar to the previous ones with perlfunc.pod. Here, though, we open a DBM file called pf_data as the DBM hash %DB. In case that file had any leftover data, we set the hash to an empty list. That's normally a rare thing to do, but we want to wipe out the entire database, in case a previous run of this program left incorrect or out-of-date data in the file. (After all, there's a new perlfunc.pod with each new release of Perl.)

    When we find an identifier, we need to store its line number (from $.) into the database. The statement that does that uses the high-precedence short-circuit || operator. If the database entry already has a value, that value is true, so the old value is used. If the database entry is empty, that's false, so the value on the right ($.) is used instead. We could have written that line in a shorter way, like this:

    $DB{$1} ||= $.;

    When the program is done, it says so. That's not required by the exercise description, but it lets us know that the program did something; without that line, there would be no output at all. But how can we tell that it worked correctly? That's the next exercise.

  2. Here's one way to do it:

    dbmopen my %DB, "pf_data", undef or die "Can't open dbm file: $!";
    my $line = $DB{$ARGV[0]} || "not found";
    
    print "$ARGV[0]: $line\n";

    Once we have the database, it's simple to look something up in it. Note that in this program, the third argument to dbmopen is undef, since that file must already exist for this program to work.

    If the entry for $ARGV[0] (the first command-line parameter) isn't found in the database, we'll say it's not found, using the high-precedence short-circuit ||.

  3. Here's one way to do it:

    dbmopen my %DB, "pf_data", undef or die "Can't open dbm file: $!";
    
    if (my $line = $DB{$ARGV[0]}) {
      exec 'less', "+$line", '/path/to/perlfunc.pod'
        or die "Can't exec pager: $!";
    } else {
      die "Entry unknown: '$ARGV[0]'.\n";
    }

    This starts out like the previous one, but uses exec to start up a pager program if it can, and dies if it can't.



Library Navigation Links

Copyright © 2002 O'Reilly & Associates. All rights reserved.