デフォルトの出力ファイルハンドルを変更する、または、I/O 多重化をする
select
には、デフォルトの出力ファイルハンドルを変更する機能と、I/O 多重化をする機能の 2 つの機能があり、
それぞれで構文が異なります。
引数を与えなければ、デフォルトの出力ファイルハンドルを返します。 FILEHANDLE が指定されたら、FILEHANDLE をデフォルトの出力ファイルハンドルにセットし、 直前までセットされていたファイルハンドルを返します。
select
でデフォルトの出力ファイルハンドルを変更すると、2 つの効果が現れます。
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 にちゃんと出力される
select
は引数を 4 つ与えることで、
select(2) システムコールを呼び出します。
I/O 多重化に使われるようですが、残念ながら詳細は筆者は良く分かりません。
ただ、この引数 4 つを与える select
は、よく sleep
や
Time::HiRes
の
sleep
の代わりに使われることがあるようです。
print "2.45 秒だけ待機します。\n";
select undef, undef, undef, 2.45;
print "待機を終了しました。\n";
このように第 1 から 第 3 引数まで undef
を指定し、第 4 引数に待機したい秒数を指定します。
この秒数は小数を指定することができます。しかし、現在は Time::HiRes は標準モジュールということもあり、
待機の目的で select
を使う必要性は薄いかもしれません。