読者です 読者をやめる 読者になる 読者になる

sironekotoroの日記

Perl と Mac の初心者の備忘録

Perl言語プログラミングレッスン[入門編] 第11章 練習問題

11-5

  • ファイルだったらその中身を、ディレクトリだったらファイル一覧を表示する
  • 自分の解答
use strict;
use warnings;

my $hikisu = $ARGV[0];

unless (defined $hikisu){
    print 'no HIKISU',"\n";
}
elsif ( -f $hikisu ) {
    #ファイルだったら
    open( FILE, $hikisu );
    while (<FILE>) {
        print $_;
    }
    close FILE;
}
elsif ( -d $hikisu ) {

    #ディレクトリだったら
    opendir( DIR, $hikisu );
    while ( readdir DIR ) {
        print $_, "\n";
    }
    closedir(DIR);
}
  • 結城先生の解答は、引数が複数あった場合や、引数に指定したものが存在しない場合、に対処できるようにしていた。
  • エラーをどこまで想定できるかが初心者と上級者の違いなんだろうか
use strict;
use warnings;

if ( @ARGV == 0 ) {

#引数が無かったら使い方を表示してスクリプト終了させてる
    print "Usage: perl showit.pl file-or-dir ...\n";
    exit(-1);
}

foreach my $name (@ARGV)
{ #引数が複数だった場合のために、配列から取り出して判断
    unless ( -e $name ) {
        die "'$name' does not exist"  #引数が無かった場合には終了
    }
    elsif ( -f $name ) {
        open( FILE, $name ) or die "$name : $!";
        foreach my $line (<FILE>) {
            print $line;
        }
        close(FILE);
    }
    elsif ( -d $name ) {
        opendir( DIR, $name ) or die "$name: $!";
        foreach my $entry ( readdir(DIR) ) {
            print $entry, "\n";
        }
        closedir(DIR);
    }
    else {
        die "I cannot show '$name' to you.\n";
    }

}

sublime text2にスニペット追加

  • or die "$!"
  • しかし、"$"って入れてtabtriggerを設定すると、入力が消えてしまう。
  • "\$!"と設定して希望通りの動作をすることを確認。エスケープ重要。

11-6

  • 3時間くらいかかった・・・
  • しかも、結城先生の本には出てこないハッシュリファレンスまで使って
  • 元データは__DATA__に設置。
use strict;
use warnings;
use Data::Dumper;

my $magazine;
my $num = 0;
my @array;

for my $i ( sort <DATA> ) {
    if ( $i =~ /(^No\.\d+)(\s+)(\d+)/ ) {
        $magazine->[$num]->{title}  = $1;
        $magazine->[$num]->{copies} = $3;
        $num++;
    }
}

for my $i ( 0 .. $num - 2 ) {
    my $dif = "$magazine->[$i]->{title}" . ' -> '
        . "$magazine->[ $i + 1 ]->{title}" . ':';
    my $sa = $magazine->[ $i + 1 ]->{copies} - $magazine->[$i]->{copies};
    push @array, $dif . $sa;
}

open( FILE, '> mmout.txt' ) or die "$!";
for my $i ( reverse @array ) {
    print FILE $i, "\n";

}
close FILE;
  • 結城先生だと、x行目とX+1行目という風にとらえて構築してるみたい。
  • ただ、それだと最初の行は比較対象が無いので、1行目かどうかを判断する変数を用意して、条件分岐させてる
use strict;
use warnings;

my $outfile = 'mmout_yuki.txt';
open( OUTFILE, "> $outfile" ) or die "$outfile : $!";

my $firstline = 1;
my ( $lastvol, $lastcount );
foreach my $line (<DATA>) {
    my ( $vol, $count ) = split( /\s+/, $line );
    unless ($firstline){
        my $up = $lastcount - $count;
        print OUTFILE "$vol -> $lastvol: $up\n";
    }
    ($lastvol , $lastcount) = ($vol,$count);
    $firstline = 0;
}
close(OUTFILE);

11-7

  • ハッシュに配列の要素を追加する方法すっかり忘れてて、自分の脳レベルに悲しくなる
use strict;
use warnings;
use Data::Dumper;

my $seiseki;

open( FILE, "data.txt" ) or die "$!";
for my $i (<FILE>) {
    my ( $yomi, $name, @score ) = split /,/, $i;
    my $sum;
    for my $score (@score) {
        $sum += $score;
    }

    #    print $name, $sum, "\n";
    push @$seiseki, { name => $name, score => $sum };

}
close FILE;

my $sorted;
@$sorted = sort { $b->{score} <=> $a->{score} } @$seiseki;

for my $i (@$sorted){
    print $i->{name},$i->{score},"\n";
    
}
  • 結城先生の解答は豪快だわ
  • まるまる1行をハッシュのkeyにしてる。想像もつかんかったわ・・・
  • カンマを見ると区切りたくなる病に・・・いややっぱり、1行を丸まるkeyってのは考えつかん
use strict;
use warnings;
use Data::Dumper;

open( FILE, 'data.txt' ) or die "$!";
my @file = <FILE>;
close(FILE);

my %line_to_sum;
my %line_to_name;
foreach my $line (@file) {
    my ( $yomi, $name, @score ) = split( /,/, $line );
    my $sum = 0;
    foreach my $score (@score) {
        $sum += $score;
    }
    $line_to_sum{$line}  = $sum;
    $line_to_name{$line} = $name;
}

print Dumper %line_to_name;

foreach my $line ( sort { $line_to_sum{$b} <=> $line_to_sum{$a} } @file ) {
    print $line_to_name{$line}, "\t", $line_to_sum{$line}, "\n";
}

11-8

  • これは簡単だった
  • というか、いままで「ファイルグロブ」ってのがよくわからなかったんだけど、とっかかりを掴めたわ。
use strict;
use warnings;

for my $file (<*.*>) {
    if ( -M $file < 1 ) {
        print '(DAY)', $file, "\n";
    }
    elsif ( -M $file < 7 ) {
        print '(WEEK)', $file, "\n";
    }
    else {
        print '(OLD)', $file, "\n";
    }
}
  • 次回は付録のCGIに挑戦する予定。
  • 「いまさらCGI?事態はWAFでしょ!!!!」とか思っていたけど、やはり一度は触れておかなくては行けない気がする。
    • perlやっててCGI知らないってのは、なんかしっくりこないよね。