続・初めてのPerl 第8章 「ファイルハンドルへのリファレンス」
練習問題の回答をメモ。
ex08-1
#!/usr/bin/perl use strict; use warnings; use IO::Tee; my $choice; while (1) { print "1: File, 2: Scalar, 3: Both, q: quit\n"; print "Which of above do you want your output to go?: "; chomp($choice = <STDIN>); last if $choice =~ /^\s*[123]\s*$/; exit 0 if $choice =~ /^\s*q\s*$/i; print "\nPlease choice between 1-3!\n" } my $fh; my $scalar_output; # スカラー出力の場合に使う my $file_name = 'hoge.out'; if ($choice eq "1") { open $fh, '>', $file_name or die "Could not open $file_name: $!"; # p.98 } elsif ($choice eq "2") { open $fh, '>', \$scalar_output or die "Could not open scalar: $!"; } else { open my $fh_tmp1, '>', $file_name or die "Could not open $file_name: $!"; # p.98 open my $fh_tmp2, '>', \$scalar_output or die "Could not open scalar: $!"; $fh = IO::Tee->new($fh_tmp1, $fh_tmp2); } my $dow = (localtime)[6]; my $day = localtime; my @day_of_week = qw(Sun Mon Tue Wed Thu Fri Sat); print $fh "date: $day $day_of_week[$dow]\n"; print "$scalar_output\n" if $choice =~ /^\s*[23]\s*$/;
$0(プログラム名) がファイルの名前として利用できたね。
ヒアドキュメントを利用できたね。
解答で使われていた $$ はプロセスID が格納されているよ。
ex08-2
#!/usr/bin/perl use strict; use warnings; use IO::File; @ARGV = "log_file.txt"; my %file; while (<>) { my $line = $_; unless ($line =~ /^(\S+):/) { warn "skipping the line missing name: $line"; next; } # my $name = (split /:/, $line)[0]; my $name = lc $1; my $fh = IO::File->new(">> $name.info") or warn "Could not open $name: $!\n"; print $fh $line; }
この問題のヒントで、「名前をキーとし、出力ファイルに対応するIO::Fileオブジェクトを値とするハッシュを使いましょう。」とあるけど、ファイルを上書きモードで開けばハッシュを使うまでも無い気がする。いや、だけどよく考えてみると、毎回ファイルを開いている分だけ処理が重くなるのかな…。
ex08-3
#!/usr/bin/perl use strict; use warnings; use IO::Dir; foreach (@ARGV) { my $dir_fh = IO::Dir->new($_) or die "could not open $_: $!\n"; print "$_ has files below:\n"; while (defined(my $file = $dir_fh->read)) { print "$file\n"; } print "\n"; }
解答を見たら、@ARGV をチェックして、ディレクトリ名でないものを除外していた。確かにこの処理は必要だな。
反省点
練習問題の字面だけを読まないで、意味を察して取り組もう。ほとんど意味の無いプログラムになっちゃうかもよ。