11章練習問題
問1
#!/usr/bin/perl use strict; use warnings; my($input_file, $output_file, $pattern, $replace); sub get_response { print $_[0]; chomp(my $response = <STDIN>); $response; } $input_file = get_response "入力ファイル名を入力してください。\n"; $output_file = get_response "出力ファイル名を入力してください。\n"; if (-e $output_file) { my $overwrite = get_response "上書きしますか? [y/n] "; if ($overwrite ne "y" && $overwrite ne "Y") { print "終了します。\n"; exit 0; } } $pattern = get_response "サーチパターンを入力してください。\n"; $replace = get_response "置換文字列を入力してください。\n"; open IN, $input_file or die "$input_fileをオープンできません。 $!"; open OUT, ">$output_file" or die "$output_fileをオープンできません。 $!"; while (<IN>) { s/$pattern/$replace/g; print OUT; }
これだと、置き換え文字列にマッチ変数や逆スラッシュエスケープは使えない。$patternが変数展開される時に、$1はドル記号と数字の1として扱われてしまうかららしい。もう一段階、変数を展開する方法があるらしいが、よくわからない。
それと、ファイルのオープンに失敗した場合、サーチパターンと置き換え文字列を入力してもらっても無駄になるので、先にファイルをオープンした方がよかった。
問2
#!/usr/bin/perl use strict; use warnings; sub get_file_info { my $file = shift @_; return "存在しません。" unless -e $file; my @file_info; push @file_info, (-r _) ? "読○" : "読×"; push @file_info, (-w _) ? "書○" : "書×"; push @file_info, (-x _) ? "実○" : "実×"; return @file_info; } for my $file (@ARGV) { my @file_info = get_file_info $file; print "$file:@file_info\n"; }
問3
#!/usr/bin/perl use strict; use warnings; my($oldest_file, $oldest_day); # 存在するファイル名が見つかるまでループ while ($oldest_file = shift @ARGV) { last if -e $oldest_file; } die "有効なファイル名がありません。\n" unless $oldest_file; $oldest_day = (stat _)[9]; for my $file (@ARGV) { next unless -e $file; # ファイルがなければスキップ my $day = (stat _)[9]; ($oldest_file, $oldest_day) = ($file, $day) if $oldest_day > $day; } my($sec, $min, $hour, $day, $mon, $year) = localtime $oldest_day; printf "最も古いファイルは%d年%d月%d日に作成・変更された%sです。\n", 1900 + $year, $mon + 1, $day, $oldest_file;
最初は、(stat _)[9]ではなく、-M _としていたのだが、-Mが返す値はタイムスタンプではないので、更新日が全て1970年1月1日になってしまった。-Mが返すのは更新日のタイムスタンプではなく、更新されてからの日数なので注意。