File-Random-0.17 > File::Random

名前

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, <[email protected]>

作者

Janek Schleicher, <[email protected]>

参考資料

Tie::Pick Data::Random Algorithm::Numerical::Sample

翻訳者

川合 孝典([email protected])