§1.7 事務方


作成日:2001/06/10(日)

ここ何回か複数のユーザに対応すべくいろいろとやってきましたが、いっそのことユーザ名とパスワードを別のファイルにまとめておきましょう。 そうすればユーザ登録やパスワードの変更時にいちいちスクリプトを変更しなくてもすみます。 「事務は事務方に」というわけです。
 まずメモ帳などで次のようなファイルを作成します。

 can,nyanko
 masa,wanko
 hide,buhibuhi

ファイル名はuser.datとしておきます。

では,この事務方ファイルを使って改造版を作りましょう。 このファイルをスクリプトに読みこませるには、まずファイルを開かなければいけません。 Perlではファイルを開くための関数としてopen関数があります(わかりやすぅ〜)。

 open(IN, "<user.dat");

( )内を見るとまずINとあります。 これはファイルハンドルといって,スクリプトとデータファイルを結びつけるものです。 スクリプトはこのファイルハンドルを通じてuser.datというファイルを読んだり書いたりします。 ファイルハンドルは大文字で書く習慣になっています(他の変数名などとぶつからないようにするため)。
 ファイルハンドルのあとにダブルクォートで囲んでファイル名がありますが,その前に<があります。 これはファイルを「読取専用」として開くことを表しています。
 ファイルを開いたら,その中のデータを読み込みましょう。

 @data = <IN>;

と書きます。 これによって、ファイルハンドルINによって結び付けられたuser.datの中身を,改行までを一つの要素と見て配列@dataに代入します。 今の場合,

 $data[0] = 'can,nyanko\n';
 $data[1] = 'masa,wanko\n';
 $data[2] = 'hide,buhibuhi';

となります。
 ここで一つ種明かしをします。 今まで何度も、

 $username = <STDIN>;

と書いてきました。 実はSTDINというのは標準入力(普通はキーボード)に与えられた特別なファイルハンドルなんです。 そして上のように書くことで,キーボードからの入力を,Enterキーが押されるまで受け取って,$usernameというスカラー変数に代入するように命令していたんです。
 さて最後,ファイルからデータを読み取ったらファイルを閉じましょう。 これもわかりやすく、

 close(IN);

と書きます。 なんとも直感的ですね。
 では,改造版スクリプトです。

 01: open(IN, "<user.dat"); #ファイルオープン
 02: @data = <IN>; #データを読み込んで
 03: close(IN); #ファイルクローズ
 04: foreach(@data){
 05:   ($name, $passwd) = split(/,/, $_);
 06:   chomp($passwd);
 07:   $passwd{$name} = $passwd;
 08: }
 09: print "あなたのお名前なんてーの?:";
 10: $yourname = <STDIN>;
 11: chomp($yourname);
 12: $namecheck = 0;
 13: foreach $username (keys %passwd) {
 14:   if($yourname eq $username){
 15:     $namecheck = 1;
 16:     print "よっ、$yournameちゃん、どう?最近。\n";
 17:     $pwdcheck = 0;
 18:     for($j = 0; $j < 3; $j = $j + 1){
 19:       print "パスワード入力:";
 20:       $yourpasswd = <STDIN>;
 21:       chomp($yourpasswd);
 22:       if($yourpasswd eq $passwd{$username}){
 23:         print "OK. 入ってイイよ〜\n";
 24:         $pwdcheck = 1;
 25:         last; #forループから脱出(A)
 26:       } else{ #条件式が偽の場合ここを実行
 27:         print "おや、パスワード間違えた?\n";
 28:       }
 29:     } 
 30:   #(A)ここへ出てくる
 31:   } else{
 32:     next; #次のループへ(B)
 33:   }
 34:   if(($namecheck == 1) && ($pwdcheck == 1)){
 35:     last; #名前もパスワードも一致したら(C)
 36:   } elsif($pwdcheck == 0){
 37:     print "ムム、お主何やつ!\n";
 38:   }
 39: #(B)ここへ移動して次のループへ
 40: }
 41: #(C)ここへ移動
 42: if($namecheck == 0){
 43:   print "あれ? 名前が登録されてないよ。\n";
 44: }

スクリプトを見ていきましょう。 1行目でuser.datを開いて,2行目でデータを読み込んで,3行目でファイルを閉じています。 これは上で説明したとおりですね。 4行目。 前回も登場したforeachループですが,チョット変です。 foreachループの構文は,

 foreach $val (@array){
  実行文;
 }

となっていました。 そして、@arrayの要素を順に1つずつ$valに代入して,それに対して実行文を実行します。 ですが,上のスクリプトの4行目には$valにあたる部分がありません。 でも安心してください。 Perlの書き方はこれでもOKです。 foreachループでこの$valにあたる部分を省略した場合,Perlは特別なスカラー変数$_というのを用意していて,そこへ代入して処理をします。 ああ、Perlよ、君はなぜそんなにおおらかなんだ!
 5行目を見てください。 新しい関数splitが登場しました。 ( )内を見ると,最初に/,/とあり,そのあとに$_とあります。 split関数は,$_の中を見て,そこに/で挟まれた文字(ここではカンマ)を見つけると,その前後を区切ってくれます。 もう少し詳しく言うと,まずこの時点で$_には、

 can,nyanko\n

という文字列が入っています。 split関数はこの文字列を見て,カンマ(,)を見つけると,その前後,つまりcanとnyanko\nを区切ってくれます。 そしてそれぞれを左辺の変数に代入してくれるのです。
 6行目。ここで$passwdの最後にある改行文字を除いて7行目でハッシュ%passwdに値をセットしています。 このforeachループによって,前回作成した%passwdと同じ物が出来たことになります。 あとはスクリプトには変更はありません。

さて、第1章も大詰めです。 次回は「スクリプト内アウトソーシング」についてお話します。


「§1.6 続・嬉しい悩み」へ 「§1.8 アウトソーシング」へ
ソフトバンク パブリッシング株式会社

Copyright (C) can All Rights Reserved
e-mail:ishiki@mrj.biglobe.ne.jp