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が返すのは更新日のタイムスタンプではなく、更新されてからの日数なので注意。