=encoding euc-jp =head1 NAME File::Random - ファイルをランダムに選択するためのPerlモジュール =head1 概要 use File::Random qw/:all/; my $fname = random_file(); my $fname2 = random_file(-dir => $dir); my $random_gif = random_file(-dir => $dir, -check => qr/\.gif$/, -recursive => 1); my $no_exe = random_file(-dir => $dir, -check => sub {! -x}); my @jokes_of_the_day = content_of_random_file(-dir => '/usr/lib/jokes'); my $joke_of_the_day = content_of_random_file(-dir => '/usr/lib/jokes'); # あるいはより短く my $joke = corf(-dir => '/usr/lib/jokes'); my $word_of_the_day = random_line('/usr/share/dict/words'); my @three_words = random_line('/usr/share/dict/words',3); # あるいは my ($title,$speech,$conclusion) = random_line('/usr/share/dict/words'); =head1 説明 このモジュールは(CGIスクリプトで見られるような)ランダムなファイルの選択の ルーチン・ワークを簡単にします。 それはうんざり(そしてエラーになりがち)で常に以下のように書くものであるために、 そうしました。 my @files = (<*.*>); my $randf = $files[rand @files]; あるいは opendir DIR, " ... " or die " ... "; my @files = grep {-f ...} (readdir DIR); closedir DIR; my $randf = $files[rand @files]; 特別なチェック・ルーチンで検索して、サブディレクトリをランダムに選択する ものを書くこともうんざりしますし、大変危険です。 ファイルからランダムに行を選ぶ簡単で標準的な作業も実装されています。 =head1 関数 =head2 random_file =over 2 =item random_file 指定されたディレクトリからランダムに選択されたファイル(の名前)を返します。 もしディレクトリが空であれば、undefが返されます。3つのオプションがあります: my $file = random_file( -dir => $dir, -check => qr/.../, # あるいは sub { .... } -recursive => 1 # あるいは 0 ); オプションについて見てみましょう: =over 4 =item -dir (-d あるいは -directory) ファイルがやってくるべきディレクトリを指定します。 C<-dir>オプションが指定されなければ、現在のディレクトリからランダムな ファイルが使われます。つまりC<-dir>オプションのデフォルトは'.'です。 =item -check (-c) C<-check>オプションで、それぞれのファイル名が従うべき正規表現あるは、 ファイル名を引数として取得するサブルーチンのどちらかを指定することが できます。引数として渡されたファイル名には相対パス(C<-dir>ディレクトリ あるいは現在のディレクトリからの相対)が入ります。 ローカル化されたC<$_>の値が暗黙のうちに渡されます。 そしてそれは引数配列の先頭のパラメータC<$_[0]>でもあります。 C<-check>は正規表現やサブルーチン以外は何も受け取らないことに 注意してください。'/.../'のような文字列では動きません。 デフォルトでは何もチェックされません(undef)。 =item -recursive (-r or -rec) サブディレクトリもファイルを調べられることを可能にします。 各ファイル、そのファイル・ツリーでの位置に関わらず、 選ばれるチャンスは同じです。 現在では、ランダムに選ばれるファイルの与えられたサブディレクトリあるいは 現在のディレクトリからの相対パスにはファイル名が含まれます。 すべてのtrue値は再帰的な動きを有効とし、全てのfalse値は 無効にします。デフォルトはfalse(undef)です。 私は再帰的なルーチンを(Cを使って)非常に守備的に プログラムしています。 そのため再帰的な動きを有効にすると、プログラムは若干遅くなります :-) ファイルの再帰的検索に関連する詳細とバグについてはCを ご覧ください。 =item 未定義のオプション(unknown options) 警告を出します。 未定義のオプションは無視されます。 大文字/小文字は別になることに注意してください. (おそらく、1日に一度、私はそれを変更するでしょう) =back =back =head2 関数 content_of_random_file (あるいは corf) ランダムに選択されたランダム・ファイルの内容を返します。 リスト・コンテキストでは選択されたファイルの行の配列を返します。 スカラー・コンテキストではファイル全体が入った複数行の文字列を返します。 行はchompされません。 この関数はCメソッドと同じパラメータで似たような行動を とります。 C<-check>オプションはファイルの内容をでななく、渡されたファイル名を 受け取ることに注意してください。 長いCの代わりに、別名Cを使うことも出来ます。 (しかしCあるいは Cのどちらかをいうことを忘れないでください) =head2 関数 random_line($filename [, $nr_of_lines]) (既存の)ファイルから、1あるいはC<$nr_of_lines>行のランダムな行を返します。 ファイルが空であれば、undefが返されます。 1行を返すために使われているアルゴリズムはFAQからのものです。 詳細はCをご覧ください。 1行以上(C<$nr_of_lines E 1>)について、私はほぼ同じアルゴリズムを 使っています。重複して返されることもあるので、特に返られる行は 標本とはなりません。 Cの結果はCに 非常によく似ています。ファイルは1回ではなC<$nr>回読み込むために、後者はあまり 効率的ではないだけです。 そのアルゴリズムでは、メモリ上で同時にファイルの2行分しか 必要としないためにこれは大きなファイルに対しても同様に機能します。 C<$nr_of_lines>はオプションの引数でデフォルトでは1です。 1より大きいC<$nr_of_lines>をつけてCをスカラー・コンテキストで 呼び出すことは、あまり有意義ではないので、警告を出します。 C<$nr_of_lines>が0でも、警告を出します。 以下のように書くこともできます my ($line1, $line2, $line3) = random_line($fname); そしてrandom_lineはランダムに選択された行3つのリストを返します。 Cはあなたが何行ほしいかを見つけ出そうと、努力します。 しかし神の使いではないので、 my @line = random_line($fname); は以下のように解釈されます my @line = random_line($fname,1); =head2 EXPORT デフォルトでは何もありません。 関数random_fileを以下の方法でエクスポートすることができます C, C あるいはもっと簡単に C. 利用者がrandom_fileでランダムな内容のファイルを作成する方法を書きましたが、 私としてはできるだけ名前空間を汚したくはありませんでした。 もし私が偏執的だと思うのであれば、教えてください。 そうしたら、それをエクスポートしようと思います。 =head1 依存関係 このモジュールは以下の他のモジュールやライを必要とします: Want テストのためには、さらに多くのモジュールを必要とします: Test::More Test::Exception Test::Class Set::Scalar File::Temp Test::Warn Test::ManyParams Test::Class それ自身は、以下の追加のモジュールを必要とします: Attribute::Handlers Class::ISA IO::File Storable Test::Builder Test::Builder::Tester Test::Differences これらのモジュールはテストのためだけに必要です。 これらがなかったとしても、モジュールを動かすことはできます。 これらのモジュールは、File::Randomそのものではなく、 私のテストルーチンのためだけに必要です。 (しかしいずれにしても、モジュールのほとんどはインストールするのは とてもよい考えです)。 =head1 TODO CのためのA C<-firstline> や C<-lines => [1 .. 10]> オプションが便利になるでしょう。 コードをとても読みやすくしようとすれば、スピードも改善できるでしょう。 しかし場合によっては若干遅くなるかもしれません。 便利になりそうなことであれば、気軽に提案してください。 =head1 バグ このモジュールがいくつかのランダムなデータを扱っているために、 ちょっとテストしくにくくなっています。 そこでテストが間違っているかもしれません。すべてがOKであっても... これを避けるため、私は多くのテストを実行しました。 そのため試験が間違っていることの可能性は0.0000000001%未満ぐらいでしょう。 テストに非常に長い時間を必要とするという欠点はありますが :-( 私は'\\'を使うWinのように'/'とは違うパス区切り文字を持つOSで テスト・ルーチンが動くのか、はっきりとは確信していません。 多分、たれかが試して、その結果を教えてくれるでしょう。 [しかしWin*が本当に大きなバグであることを忘れないでください] =head1 著作権(=COPYRIGHT) This Program is free software. You can change or redistribute it under the same condition as Perl itself. Copyright (c) 2002, Janek Schleicher, Ebigj@kamelfreund.deE =head1 作者 Janek Schleicher, Ebigj@kamelfreund.deE =head1 参考資料 L L L =head1 翻訳者 川合 孝典(GCD00051@nifty.ne.jp)