初めてのPerl 第16章

練習問題の回答をメモ。

ex16-1
#!/usr/bin/perl
use strict;

my $pod_path = `perldoc -l perlfunc`;
open POD,  $pod_path or die "Cannot open $pod_path: $!";
# 上の2行は以下の1行で置き換えられる。while(<POD>) を while(<>) に変える必要あり。
# @ARGV = `perldoc -l perlfunc`;

my %DB;
dbmopen(%DB, "pod_db", 0644)
    or die "Cannot open pod_db: $!";
%DB = ();

while (<POD>) {
  if (/^=item\s+([a-zA-Z_]\w*)/) {
    $DB{$1} = $DB{$1} || $.;
  }
}

# DBM の内容を表示して確かめてみる
while (my($func, $line_num) = each(%DB)) {
  print "<<$func>> first appeared on line <<$line_num>>\n";
}
ex16-2
#!/usr/bin/perl
use strict;

dbmopen(my %DB, "pod_db", undef)
    or die "Cannot open pod_db: $!";

my $func_name = $ARGV[0];
my $line_num = $DB{$func_name} || "Not Found";

print "<<$func_name>>: <<$line_num>>\n";

あれー、なんか警告っぽいのが出る…。

% perl -w ex16-2.pl hoge
Use of uninitialized value in dbmopen at ex16-2.pl line 4.
<<hoge>>: <<Not Found>>

dbmopen の第3引数に undef を指定すると、この警告が出るみたいなんだけど、何でだろう?0644 とかを指定すると出ないんだけどな。ex16-3 でも同じ警告が出る。

ex16-3
#!/usr/bin/perl
use strict;

dbmopen(my %DB, "pod_db", undef)
    or die "Cannot open pod_db: $!";

my $func_name = $ARGV[0];

if (my $line_num = $DB{$func_name}) {
  my $pod_path = `perldoc -l perlfunc`;
  exec "less +$line_num $pod_path" or die "less couldn't run: $!";
} else {
  print "Not found: $func_name\n";
}

反省点(と感想)

if文の代わりに、OR演算子|| をうまく使おう。
DBMハッシュをうまく利用すればデータの扱いが楽になるかも。