僕のYak Shavingは終わらない

車輪の再発明をやめたらそこには壮大なYakの群れが

『初めてのPerl第5版』第9章〜終わりまで

9章 正規表現によるテキスト処理

なんかめんどくさいから最後にまとめやるよ。

9.1 s///を使って置換を行なう
  • 9.1.1 /gによるグローバルな置換
  • 9.1.2 別のデリミタを使う
  • 9.1.3 オプション修飾子
  • 9.1.4 結合演算子
  • 9.1.5 大文字と小文字の変換
9.2 split演算子
9.3 join関数
9.4 m//をリストコンテキストで使う

第5版より追加。
なにこれカッコイイ!

$_ = "hoge:fuga:piyo";

#とりあえず普通にsplit
print join " ", split /:/;
print "\n";

#マッチをリストコンテキストで
print join " ", /\w+/g;
print "\n";

#ハッシュに入れてしまう
$_ = "hoge:hogeko:piyo:piyoko";
my %hash = /(\w+):(\w+)/g;
while (my ($last, $first) = each %hash){
    print "$last=$first\n";
}

Perlすごい。

9.5 より強力な正規表現機能
  • 9.5.1 欲ばりでない量指定子

正規表現が遅い理由が書かれている!!

  • 9.5.2 複数行のテキストに対するマッチ

量指定子にはてなをつけるとバックトラックのやり方が逆になるみたい。
必ずしも高速化出来るわけではないが、これで正規表現をチューニングできることがわかった。

  • 9.5.3 たくさんのファイルを更新する
chomp(my $date = `date`);
$^I=".bak";

while(<>){
    s/^hoge(.*)/piyo$1/;
    print;
}
perl -p -i.bak -w -e 's/piyo/hoge/g' hoge
9.6 練習問題

やばい楽しい!

#perldoc -l perlfuncを実行した結果をいれる
@ARGV = ("/home/YOUR_USER_NAME/perl5/perlbrew/perls/perl-5.12.4/lib/5.12.4/pod/perlfunc.pod
");

my %item_list;
while (<>) {
    chomp;
    if (/^=item\s+([A-Za-z_]\w*)/) {
        #print "Matched : |$`<$&>$'|\n";
        #print "Matched : $1\n";
        if(exists $item_list{$1}){
            $item_list{$1} +=1;
        }else{
            $item_list{$1} =1;
        }
    }#else{
    #    print "No Match\n";
    #}
}

foreach(sort keys %item_list){
    if($item_list{$_} > 3){
        printf "%-12s :%2d\n",$_, $item_list{$_};
    }
}

#無駄にsplitとjoinを使ってみる
#%item_listのkeysはすべてのPerl識別子の名前がリストで入っていることを利用
#以下は結局%item_listのkeysをそのまま表示
foreach(split /\s+/, join " \t     ", keys %item_list){
    print "$_\n";
}

第5版の練習問題は変更されていますね!!

my @filelist = @ARGV;
my %filehash;
print "Now load files :\n";
foreach(@filelist){
    $filehash{$_} = 1;
    print;
    print "\n";
}
while(<>){
    if(/Copyright/m){
        delete $filehash{$ARGV};
    }
}
@filelist = keys %filehash;
print "Not write Copyright :\n";
foreach(@filelist){
    print;
    print "\n";
}

@ARGV = @filelist;
$^I = ".out";
while(<>){
    if(/^#!/){
        print;
        print "## Copyright (C) 2011 by Kazuhiro Homma\n";
    }else{
        print;
    }
}

ここに来て練習問題の解説が充実していることに気づいた。
2週目があったらやろう。



なごり惜しいけど次!

10章 さまざまな制御構造

10.3 式修飾子

来ました大好物!!

例えば上の最後の3行を以下の1行に変換できる。

print "$_\n" foreach(split /\s+/, join " \t     ", keys %item_list);

でも複数の修飾子(if,for,while等)は使えないんだって><残念

printf "%-12s :%2d\n",$_, $item_list{$_} if($item_list{$_} > 3) foreach(sort keys %item_list);
# Error
10.4 裸のブロック制御構造

もうちょっと詳しくやってほしかった…
returnとかがどうなるのかとか。

10.5 elsif節
10.6 オートインクリメントとオートデクリメント

意味が違うんだねぇ。

my $i=0;
my $j=0;
print "i=".($i+=1)." j=".($j++)."\n" while($i < 10);

# 結果
#i=1 j=0 k=1
#i=2 j=1 k=2
#i=3 j=2 k=3
#i=4 j=3 k=4
#i=5 j=4 k=5
#i=6 j=5 k=6
#i=7 j=6 k=7
#i=8 j=7 k=8
#i=9 j=8 k=9
#i=10 j=9 k=10
  • 10.6.1 オートインクリメントの値

書いてあった。。。
あと出現回数をカウントするのが短くなるって説明があった。
くそー確かにこう書ける。。。

#perldoc -l perlfuncを実行した結果をいれる
@ARGV = ("/home/YOUR_USER_NAME/perl5/perlbrew/perls/perl-5.12.4/lib/5.12.4/pod/perlfunc.pod
");

my %item_list;
while (<>) {
    chomp;
    if(/^=item\s+([A-Za-z_]\w*)/){
        if($item_list{$1}++){} #あれ、本見たいにかっこ良くかけない…
    }
}

foreach(sort keys %item_list){
    if($item_list{$_} > 3){
        printf "%-12s :%2d\n",$_, $item_list{$_};
    }
}
10.7 for制御構造

おそれいりました。。。

for($_ = "hajimeteno perl"; s/(.)//; ){
    print "\U$1\n";
}
  • 10.7.1 foreachとforの秘められた関係

foreachとforは等価ってのはしっていたけどね。

print "\U$_\n" for (1..10);
10.8 ループを制御する

基本は読むだけに留める。
多様するものでもないし。

10.9 三項演算子 ? :
10.10 論理演算子

これ第5版から新しく登場したやつだね!

  • 10.10.3 部分評価演算子を使って制御構造を実現する
10.11 練習問題
my $secret_num = 36;

print "数字を入力\n";
while(<>){
    chomp;
    if($_ eq "exit" or $_ eq "quit" or /\s*/){
        print "END!!\n";
        last;
    }elsif($_ == $secret_num) {
        print "sucsess!!\n";
        last;
    }elsif($_>$secret_num){
        print "Too High!\n";
    }else{
        print "Too Low!\n";
    }
}

疲れた〜

11章 Perlモジュール

ちーん今更感が…

11.1 モジュールを探す
11.2 モジュールをインストールする
11.3 単純なモジュールを使う
  • 11.3.1 File::Basenameモジュール
  • 11.3.2 モジュールの一部の関数だけを使う
  • 11.3.3 File::Specモジュール
  • 11.3.4 CGI.pm
  • 11.3.5 データベースとDBI
11.4 練習問題

次!

12章 ファイルテスト

パス!

12.1 ファイルテスト演算子
  • 12.1.1 同じファイルの複数の属性をテストする
  • 12.1.2 ファイルテスト演算子を積み重ねる
12.2 stat関数とlstat関数
12.3 localtime関数
12.4 ビット演算子
  • 12.4.1 ビットストリングを使う
12.5 練習問題

13章 ディレクトリ操作

パス!

13.1 ディレクトリツリーの中を移動する
13.2 グロブ
13.3 グロブのもう1つの書き方
13.4 ディレクトリハンドル
13.5 再帰的なディレクトリ処理
13.6 ファイルとディレクトリの取り扱い
13.7 ファイルを削除する
13.8 ファイルの名前を変更する
13.9 リンクとファイル
13.10 ディレクトリの作成と削除
13.11 パーミッションを変更する
13.12 ファイルのオーナーを変更する
13.13 タイムスタンプを変更する
13.14 練習問題

14章 文字列処理とソート

14.1 indexを使って部分文字列を探す
14.2 substrを使って部分文字列をいじる

ここら辺ってそんなに使うことになるのかなぁ?

my $big = "piyopiyo hoge fuga Hohoge";
my $small = "hoge";

#見つかった位置を返す
print index ($big, $small), "\n";
print rindex ($big, $small), "\n";

#切り取る
print((substr $big, index($big, $small)), "\n");

#切り取った部分を置き換える
substr( $big, index($big, $small)) = "World!!";
print $big, "\n";

#指定した部分だけの置換を行うことが出来る!
my $hoge = "hogehogehogehogehogehogehogehoge";
substr($hoge, -12) =~ s/hoge/fuga/g;
print $hoge,"\n";
14.3 sprintfを使ってデータをフォーマットする
  • 14.3.1 sprintfを使って金額を表示する

Perlがすごいんじゃないくて、その考え方を思いつける人がすごいんだと思うんです。

my $num = 9999999999999.12345678;

print &big_money($num), "\n"; # $9,999,999,999,999.12

sub big_money {
    my $money = sprintf "%.2f", shift @_;
    1 while $money =~ s/^(-?\d+)(\d\d\d)/$1,$2/;
    $money =~ s/^(-?)/$1\$/;
    $money;
}
14.4 高度なソート

<=>←スペースシップ演算子…ゴクリ

実際には{}の部分は関数なんだぁ。
つまり複雑な関数にすることも可能。
↓同じ

foreach(sort by_num (1,40,2,7,13,56,23,0,5,11)){
    print $_,"\n";
}

sub by_num {$a <=> $b}
foreach(sort {$a <=> $b}(1,40,2,7,13,56,23,0,5,11)){
    print $_,"\n";
}
  • 14.4.1 ハッシュを値によってソートする
my %hash = (
    hoge => 20,
    fuga => 400,
    piyo => 2,
);
# 数字の昇順
foreach(sort {$hash{$a} <=> $hash{$b}} keys %hash){
    print $_,"\n";
}

# 数字の降順
foreach(sort {$hash{$b} <=> $hash{$a}} keys %hash){
    print $_,"\n";
}
  • 14.4.2 複数のキーでソートする
14.5 練習問題
#foreach(sort {$a <=> $b} qw{17 1000 04 1.50 3.1415926525 -10 1.5 4 2001 90210 666} ){
#    printf "%12s\n",$_;
#}

my %last_name = qw{
    fred flintstone Wilma Flintstone Barney Rubble
    betty rubble Bamm-Bamm Rubble PEBBLES FLINTSTONE
};

foreach(sort {"\L$last_name{$a}" cmp "\L$last_name{$b}" or "\L$a" cmp "\L$b"} keys %last_name){
    printf "$_ $last_name{$_}\n";
}
# うわ、カッコ悪
chomp(my $str = <STDIN>);
chomp(my $sub_str = <STDIN>);

my $num =-1;
while(($num = index($str, $sub_str, $num + 1)) >= 0){
    print $num."\n";
}

15章 スマートマッチ(サイコマッチ)とgiven-when

まったくしらなかった。すげえ!(すげえ使いたくない!!)

# 配列の比較
my @a = my @b = 1..10;
print "same!\n" if @a ~~ @b;
15.1 スマートマッチ演算子
15.2 スマートマッチの優先順位

スマートマッチに順番は関係ないって書いてあるけど関係ある?

my @a = 1..10;
my $b = 2;
print "含んている!\n" if $b ~~ @a; 
print "含んている!\n" if @a ~~ $b;

ないか

15.3 given文
use 5.010;

# この書き方だとif-elsis-elseとかかわらないが…
given($ARGV[0]){
    when(/hoge/i){say 'hogeだったのさ'}
    when(/^Hoge/){say 'hoge最初から'}
    when('hoge'){say 'hogeちょうどな'}
    default     {say "hogeいない"}
}
# 以下のように書くと満たすものはすべて実行してくれる
given($ARGV[0]){
    when(/hoge/i){say 'hogeだったのさ'; continue}
    when(/^Hoge/){say 'hoge最初から'; continue}
    when('hoge'){say 'hogeちょうどな'}
    default     {say "hogeいない"}
}

え?だめ文法じゃない?最後のWhenが実行されなかくて上から2つ目のWhenまで満たすような文字を入力した場合は最後のdefaltが実行されている。。。

# 以下のように書くと満たすものはすべて実行してくれる
given($ARGV[0]){
    when(/hoge/i){say 'hogeだったのさ'; continue}
    when(/^Hoge/){say 'hoge最初から'; continue}
    when('hoge'){say 'hogeちょうどな'; break}
    default     {say "hogeいない"}
}
use 5.010;

my @list = qw{hoge Hoge fuga};
foreach(@list){
    say;
    when(/hoge/i){say "$_だったのさ"; continue}
    when(/^Hoge/){say "$_最初から"; continue}
    when('hoge'){say "$_ちょうどな"}
    default     {say "$_いない"}
}

16章 プロセス管理

飛ばす!!

16.1 system関数
  • 16.1.1 シェルの起動を避ける
16.2 exec関数
16.3 環境変数
16.4 逆クォートを使って出力を取り込む
  • 16.4.1 リストコンテキストで逆クォートを使う
16.5 プロセスをファイルハンドルとして使う
16.6 forkを使って低レベル処理を行なう
16.7 シグナルを送受信する
16.8 練習問題

17章 上級テクニック

17.1 evalによってエラーをトラップする
eval {my $hoge = 10/0}; # セミコロンがいる
print "error:",$@ , "\n" if $@;
17.2 grepを使ってリストから要素を選び出す
my @odd_numbers = grep{$_ % 2} 1..1000;
print "@odd_numbers\n";
17.3 mapを使ってリストの要素を変換する
my @numbers = map{$_ *= 2} 1..1000;
print "@numbers\n";
17.4 クォートなしのハッシュキー
17.5 スライス
  • 17.5.1 配列スライス
  • 17.5.2 ハッシュスライス
my %hoge = (
    kenta => 10,
    keiko => 99,
    kenshiro => 99342934329,
);

my @my_okiniiri_player = qw / kenta kenshiro/;

my @list = @hoge{ @my_okiniiri_player };
print "@list\n";

最後の最後で気持ち悪いと思いましたwwwww

最後に

ちょっと飛ばしてしまった部分もあったけど、
結果的にモチベーションが続かないことがわかったので潔く次にいこうかなと思います。

次は、『続』かモダンPerlで。


ふぅ。。。