sironekotoroの日記

Perl で楽をしたい

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

いよいよ最終章

  • ながかったー(まだ終わってない)

コンマ区切りの数を集計する

#data.txt
さとうはなこ,佐藤花子,65,90,100,80,73
あべかずま,阿部数馬,8,7,23,21,24
いとうこういち,伊藤光一,74,31,41,59,38
さとうたろう,佐藤太郎,100,95,98,82,61
むらまつしんじ,村松真治,55,48,79,90,88
しんどうさんたろう,進東三太郎,74,41,59,31,38
  • 自分の解答
    • Perl入学式でも同じような問題をハッシュリファレンスの例題でやったんでそれなりに自信が
    • 文字列,文字列,数字,数字,数字,数字,数字という文字列だったので、2番目の文字列@array[1]を名前として表示、数字だったら足して表示、とした。
use strict;
use warnings;

    open (FILE, 'data.txt') or die "$!";
    while (my $line = <FILE>) {
        my @array = split /,/, $line;
        my $score;
        for my $item (@array){
            if ($item =~ /\d+/){
                $score += $item;
            }
        }
        print $array[1]," ",$score,"\n";
    }
close (FILE);
  • 結城先生の解答
    • 最大の違いは、カンマで区切った変数をまとめて定義してるところ。
    • さとうはなこ,佐藤花子,65,90,100,80,73 を カンマ区切って $yomi,$name,@scoreに格納している。
use strict;
use warnings;

open( FILE, 'data.txt' ) or die "$!";
while ( my $line = <FILE> ) {
    my ( $yomi, $name, @score ) = split( /,/, $line );
    my $sum = 0;
    foreach my $score (@score) {
        $sum += $score;
    }
    print $name , "\t", $sum, "\n";
}
close(FILE);

読みでソート

  • 問題文をよく読まずに数値でソートしようとして苦戦する
    • 学生の頃、問題文をよく読まずに悶絶した思い出が蘇る
  • 自分の解答。ちなみに結城先生はforeach使ってた。
    • なんでもファイルを読み込んだwhileの中で済まそうとするのではなく、いったんリスト変数に1行ずつ取り込んで処理するのもありと。
    • 処理のループを渡す時点でソートしておく
    • 今回は各行の先頭の要素が「読み」だからそのままsortで良かったけど、カンマで区切った2要素目とかだったらどうなるんだろう。
  • 奥深い
use strict;
use warnings;

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

for my $line (sort @file){
    my ($yomi,$name,@score) = split /,/ ,$line;
    my $sum = 0;
    for my $item (@score){
        $sum += $item;
    }
    print $name ,"\t",$sum,"\n";
}

ファイルハンドルとディレクトリハンドル

  • ファイルハンドル <FILE>
  • ディレクトリハンドル readdir<DIR>

ファイルテスト演算子

  • ディレクトリハンドル操作時における-f $dir、この-fというのはファイルテスト演算子
  • 通常のファイルであれば真、そうでなければ偽

ファイルグロブ

use strict;
use warnings;

while (<*.txt>) {
    print $_,"\n";
}
  • これでカレントディレクトリの.txtファイルの一覧が出てくると。
  • 名前のパターン(*.txt)が変数(たとえば$pattern)に入っている場合には、その変数をglobで展開?してやる必要がある
my $pattern = `*.txt`;
my @files = glob($pattern);
  • この<*.txt>の部分はperl正規表現ではなく、シェル(/bin/csh)の展開機能とのこと