Hash -2-

last-modified: 25th/June/'01;
since: 1st/June/2001;

ハッシュ・データ・ベース

前節では極基本的なハッシュの使い方を見てきました。本節ではファイル内の情報をハッシュとして処理するサンプルを作ってみます。

具体的には、「名前」と「 URL 」を列記したファイルに対して名前による検索をします。

データファイルは links.dat とし、書式は「名前 = URL」とします。

links.dat>>

NEXTindex     = http://www.sugai.f2s.com/
Yahoo! Japan  = http://www.yahoo.co.jp/
Google        = http://www.google.com/
goo           = http://www.goo.ne.jp/

スクリプトの流れは、ファイルをハンドル LINKS で読み込み、等号 「 = 」を区切り文字として、前後をハッシュ %linksキーに分けて読み込みます。

ファイル情報を全てハッシュ %links に読み込んでから、「名前」をキーボード入力してURLの候補を検索します。

links.pl>>

 1:
 2:
 3:
 4:
 5:
 6:
 7:
 8:
 9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
#!/usr/bin/perl
#上の行では、 Perl のパスを記述してください。
open(LINKS, './links.dat') || die "links.dat: $!";
while(chomp($line = <LINKS>)) {
  ($key, $value) = split(/\s*=\s*/, $line);
  $links{$key} = $value;
}
close(LINKS);
@key_list = keys(%links);
$counts = @key_list;
while(1) {
  print "サイト名をどうぞ (press x to end):";
  chomp($sitename = <STDIN>);
  exit if($sitename eq x);
  $miss = 0;
  foreach $key (@key_list){
    if($key =~ /$sitename/i) {
      print "  $key; $links{$key}","\n";
    } else {
      $miss++;
    }
  }
  if($miss == $counts){
    print "No such link.","\n";
    print "Try Again: ";
  }
}
exit;

line 1-2:

コメント行で、 perl の所在地です。

line 4-9

ファイル links.dat を開いて、ファイルハンドル LINKS を結びつける。

line 6:

函数 split でファイルハンドル LINKS から読み込んだ行を区切り文字で切断してリストに代入する。

split の基本書式:

リスト・配列 = split(/正規表現/, スカラー文字列);

上のスクリプトの例の場合は、/正規表現//\s*=\s*/ になっている。 \s は「空白類文字」を表し、* はゼロ回以上の繰り返しを表すメタ文字。全体で、「 = 」の前後に空白がゼロ回以上存在する文字列にマッチする。

例えば、文字列が "Yahoo! Japan    = http://www.yahoo.co.jp" の場合、 "    = " が区切り文字になり、リスト (Yahoo, http://www.yahoo.co.jp) に変換される。

このリストが、 ($key, $value) に代入されるから、結果的に、次のようになる。

$key = Yahoo! Japan;
$value = http://www.yahoo.co.jp;

このキーと値を用いて 7 行目ではハッシュ %links を生成している。

12 行目ではキーの個数を変数 $counts に代入している。スカラーコンテキストでは、配列は要素の個数を返すことに注意。

line 11:

keys は、ハッシュの引数を配列として読み込む函数。今の場合は、ハッシュ %links の全てのキーを配列 @key_list に代入している。

line 14-30:

ここは繰り返しで、キーボード入力の文字列にマッチする「キー」に対応する「値」を出力する。

Perl では UNIX の小規模データベースを使えます。これは dbm データベースと呼ばれています。

これらのデータベースを利用するためには、 opne, close の代わりに、 tie, untie を利用します。本稿では説明しませんので、 perl に添付されているマニュアルをご覧ください。

ハッシュ関連函数

上のスクリプトでは、ハッシュのキーを配列として抜き出す函数 keys を利用しましたが、値を抜き出す values、キーと値の組を順番に返す each に関して紹介します。

以下では、ハッシュの例として、次のものを考えます:

%sites = ('Yahoo! JAPAN' => 'http://www.yahoo.co.jp/',
         'Google'       => 'http://www.google.com/',
         'SUGAI,M.'     => 'http://www.sugai.f2s.com/',
         'goo'          => 'http://www.goo.ne.jp/')

keys, values

keys はハッシュのキーを配列として返します。 values は値を配列として返します。

@array = keys(%sites);
foreach(@array){    #@array の各要素は標準変数 $_ に代入
  print "$_; url= $sites{$_}\n"; 
}

この例では、一行目を削除して、 foreach ループの条件式を次のように書き換えても結構です:

foreach(keys %sites){    #keys %sites の値(キー)が標準変数に代入される

ここで注しなければいけないことは、 keys 函数の戻り値の順番はランダムだということです。 values 函数と併用して、次のように書いたとすると、キーと値が一致しなくなります:

@array1 = keys(%sites);
@array2 = values(%sites);
foreach(@array1){
  print $_: $array2{$.-1};
}

キーや値を、何らかの順番で並べたいときには、 sort 函数を用います。

foreach(sort values %sites){
  print "$.: $_\n";
}

each

each 函数は、繰り返しの中で用いられ、「キーと値」の組を一つずつ返します。ハッシュから配列を生成しないので、実行環境のリソースをいたずらに浪費しないというメリットがあります(要素数が数千、数万以上に上るデータベースを参照する場合を考えてください)。

while(($key,$value) = each(%sites)){
  print "name = $key, url = $value \n";
}
Copyright: SUGAI, Manabu. Since: 2001
FC2> モビット