select

デフォルトの出力ファイルハンドルを変更する、または、I/O 多重化をする

select には、デフォルトの出力ファイルハンドルを変更する機能と、I/O 多重化をする機能の 2 つの機能があり、 それぞれで構文が異なります。

デフォルトの出力ファイルハンドルを変更する

構文

  • select FILEHANDLE
  • select

解説

引数を与えなければ、デフォルトの出力ファイルハンドルを返します。 FILEHANDLE が指定されたら、FILEHANDLE をデフォルトの出力ファイルハンドルにセットし、 直前までセットされていたファイルハンドルを返します。

select でデフォルトの出力ファイルハンドルを変更すると、2 つの効果が現れます。

1 つ目は、write または print にファイルハンドルが指定されなかった場合に、FILEHANDLE がデフォルトのファイルハンドルになります。 次の例は、新規にファイルを生成してテキストを書き込みます。 テキストを書き込む際に、print にファイルハンドルを指定しなくても良いように、 select でデフォルトのファイルハンドルをセットします。
open my $fh, '>', 'sample.txt';
my $prevfh = select $fh;    # デフォルトファイルハンドルを変更して、直前のデフォルトファイルハンドル (STDOUT) を取得
print "To file\n";          # ファイルに出力
close $fh;

select $prevfh;             # 変更したデフォルトファイルハンドルを元に戻す (STDOUT に戻す)
print "To STDOUT\n";        # STDOUT に出力

上記サンプルでは、事前に select でデフォルトファイルハンドルを取得しています。 しかし、ファイルへの書き込みが終わったら、デフォルトファイルハンドルを元に戻しています。

2 つ目は、出力に関連する組み込み変数が、この出力チャネルを参照するようになります。 具体的には $~$| などが影響を受けます。 次の例は、select でデフォルトファイルハンドルを変更する前と変更した後で $~ の値を標準出力に出力します。

print STDOUT $~, "\n";    # STDOUT

open my $fh, '>', 'sample.txt';
select $fh;
print STDOUT $~, "\n";    # $fh

次の例は、select でデフォルトの出力ファイルハンドルを STDERR に変更し、 $| に 1 をセットすることで、STDERR のフラッシュを有効にします。

my $prevfh = select STDERR;    # いったんデフォルトの出力ファイルハンドルを STDERR に変更
$| = 1;                        # STDERR のフラッシュを有効にする
select $prevfh;                # デフォルトの出力ファイルハンドルを元に戻す
print "OK\n";                  # STDOUT にちゃんと出力される

I/O 多重化をする

構文

  • select RBITS, WBITS, EBITS, TIMEOUT

解説

select は引数を 4 つ与えることで、 select(2) システムコールを呼び出します。 I/O 多重化に使われるようですが、残念ながら詳細は筆者は良く分かりません。 ただ、この引数 4 つを与える select は、よく sleepTime::HiRessleep の代わりに使われることがあるようです。

print "2.45 秒だけ待機します。\n";
select undef, undef, undef, 2.45;
print "待機を終了しました。\n";

このように第 1 から 第 3 引数まで undef を指定し、第 4 引数に待機したい秒数を指定します。 この秒数は小数を指定することができます。しかし、現在は Time::HiRes は標準モジュールということもあり、 待機の目的で select を使う必要性は薄いかもしれません。