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