sironekotoroの日記

Perl で楽をしたい

かんたんPerl 第4章 リストと配列

リストと配列

  • 初心者本を何冊と繰り返してきたので、この辺りはなんとかこなせた。

マジックインクリメントで文字列の生成・・・に失敗

  • ただし、勝手に課題を見つけて寄り道しまくりで時間を取られるというパターン
  • 今回はマジックインクリメント
  • これで、ランダムな文字列を生成しようと試みるも失敗
    • rand関数は置いておく
use strict;
use warnings;
use 5.010;

    # マジックインクリメントで文字列を生成・・・例えば
    # a,b,c 〜 x,y,z,0,1,2 〜 7,8,9 〜 aa,ab,ac 〜 ax,ay,az,b0,b1 
    # 〜 z9,aaa,aab
    # ってのを作りたい!

    # いける
    say "a9".."b6"; # a9b0b1b2b3b4b5b6

    # とりあえず、文字からはじめてみる、ダメ
    say "a".."9"; # abcdefghijklmnopqrstuvwxyz

    # 数字からはじめてみる、ダメ
    say "0".."z"; # 0123456789

    # うーん
    # ただまぁ、文字をインクリメントしたら数字になるって考え方がおかしいよな
    my @array = ("A" , "Z");
    print ++$_ ," " for (@array); # B  AA

    # 文字列と数字の混ざったリストを作ろう
    my @words = ( ("a".."z") ,(0..9) );
    say @words; # abcdefghijklmnopqrstuvwxyz0123456789

    # その文字列の先頭と末尾でマジックインクリメントしてみたらどうか
    say $words[0]..$words[-1]
 Error : Argument "a" isn't numeric in range (or flop) at ~
    # だめだった
  • もちろん、マジックインクリメント使わず、力技で出来なくはない。
    • こうやって本来の勉強からそれてく
    • 再帰は苦手な人
use strict;
use warnings;
use 5.010;

my @words = ( ( "a" .. "z" ), ( 0 .. 9 ) );

foreach my $word0 (@words) {
    foreach my $word1 (@words) {
        foreach my $word2 (@words) {
            foreach my $word3 (@words) {
                foreach my $word4 (@words) {
                    say "$word1$word2$word3$word4"

                }
            }
        }
    }
  • きれいなピラミッドだなぁ
  • 4桁しかないのに、4桁の全パターン表示し終わるまで約1分、表示しなければ2秒
    • パスワードの桁数が多い方が良いし、文字列の種類も多い方が良いよなぁ、と実感。
    • パスワードクラックに使う辞書攻撃の辞書って、こうやって作られるんだろうなぁ
      • もちろん、今時は「あるもの」を使うんだろうけど

かんたんPerl 第2章〜第3章

さくさく進める

  • まぁ、まだ序の口なので
    • 何冊目のPerl初心者本だよというのもある
  • とはいえ、substr や index とか普段自分が使わない関数の練習ができたのは良かった

練習問題

  • 自分の回答がいまいちスマートではなかったので、本に掲載されている答えでやってみたのだけどうまく動かない
  • かんたんPerl 初版 94p Q2 (回答550p)
    • オフセットってのは文字列の先頭位置
my $year = "January 1 February 2 March 3 April 4 May 5 June 6 July 7 Augast 8 September 9 October 10 November 11 December 12";

my $month = "Mar";  # 他の月を調べたいときはここを変更する

my $name = index($year , $month);
    # これで$monthのオフセットが得られる

my $num_s = index($year , " " , $name) + 1;
    # $monthの次に出てくる空白のオフセットを探す。
    # その次($num_s)から月の順番が始まる。

my $num_e = index($year , " " , $num_s) -1;
    # さらに次に出てくる空白のオフセットを探す
    # その前($num_e)までが月の順番である

my $len = $num_e - $num_s +1;
    # 月の順番の長さ(9月までは1,10月以降は2)を得る

my $num = substr($year , $num_s , $len);
    # 月の順番を得る

say "英語で$month$num月の事です";
  • これで1〜11月までは想定した通りに動くんだけど、12月だけ $num の取得に失敗する
  • 文字列 $year の最後が、Decmber 12"; で終わっていて、最後の空白である $num_e が取得できないのが原因
    • December 12 "; のように 12 の後に1つスペースを入れるとちゃんと動く
  • で自分だったらどうするだろう、と考える。

    • この本のこの時点までで出てきた関数 print , sort , say , undef ,length , substr , index , 四則演算に文字列連結子
    • if文使えば余裕!正規表現でも行ける!のは分かるんだけど、この縛りなかなかきつい
  • とりあえず作った。我ながら雑だと思う。

use strict;
use warnings;
use 5.010;

my $year = "January 1 February 2 March 3 April 4 May 5 June 6 July 7 Augast 8 September 9 October 10 November 11 December 12";

my $month = "Dec";

my $name = index ($year , $month);
    # 月名の開始インデックスをみつける

my $num_s = index($year , " " , $name);
    # 雑に考えて、月名の後のスペース含む3文字の中には必ず月の数字が入ることを
    # 利用
    # ex) January 1 Febrary 2
    #             ___       ___
    #         空白.数字.空白
    #
    #      October 10 November 11
    #             ___         ___
    #          空白.数字.数字

my $getMonthNum = substr($year , $num_s , 3);
    #  月名スペース後の3文字を取得

my $num = $getMonthNum + 0;
    # スペースを含む文字リテラルを、数字リテラルに変換してスペースを除去する

say "英語で$month$num月の事です";
  • これで $month にDecember を入れてもちゃんと 12と返してくれる。
  • 縛り無しで書いてみた。
    • 可読性落ちてる!
use strict;
use warnings;
use 5.010;

my $year
    = "January 1 February 2 March 3 April 4 May 5 June 6 July 7 Augast 8 September 9 October 10 November 11 December 12";

my $month = "January";

my @monthName_num = split( /(\w+\s\d+)/, $year);
    # 月名 (スペース) 月の数字
    # の文字列要素に分割して、配列に格納する

my $hash_ref;
    # 格納用ハッシュリファレンス

foreach (@monthName_num) {
    if ( $_ =~ /(\w+)\s(\d+)/ ) {
        $hash_ref->{$1} = $2;
    }
    # 正規表現で月名と数字を分けてハッシュリファレンスに格納する
}

say "英語で $month$hash_ref->{$month} 月の事です";

業務に役立つPerl 終了 & かんたんPerl 勉強中

業務に役立つPerl 終了

  • しばらくblog書いてなかった・・・けど、週末ごとに勉強は続けてて「業務に役立つPerl」を終えました。
  • もともと、つまみ食いしながら内容を拾ってはいたのだけど、通して全章をやったのは初めて。
  • これをPerlの勉強1冊目に選ぶ人はレアだと思うけど、2〜3冊目であれば十分に楽しいのではないだろうか。
  • なにより、勉強している内容で仕事楽できそう!って思えるのが良かった。
  • あと、Perlオブジェクト指向についても解説してて、ちょっとだけ分かった気がする。
    • ただし、自作のプログラミングで生かせるレベルには達しなかった

かんたんPerl の勉強中

  • おそらく、最後に読むPerl初心者本?になりそうな「かんたんPerl

  • 初めて通して一冊読み終えられたPerl本が深沢先生の「すぐわかるPerl」だったので、迷いなくamazonで注文。

    • 最初に買ったのはオライリーの「はじめてのPerl」第5版で、わりとすぐ挫折した
  • 第一章の章末問題はあるある〜な内容で、目grepだけでは厳しい内容
    • でも、だいたい分かる。というか、予想がつく。
  • この本を終えたら「すぐわかるオブジェクト指向Perl」をやる予定。
    • 春くらいには着手できるかな。

Perl以外

  • Mojoliciousとか勉強しているときに、Webページのデザインとか、そもそもCSSとかまともに勉強した事ないことを認識し、「HTML5/CSS3 モダンコーディング」で勉強中。

  • ただ、これを1冊目に選んだのは失敗だった。

    • ある程度のCSS3の知識がある事を前提としている本だった
    • もちろん、コードを書いていけばちゃんときれいなページができる
    • つか、CSSだけでこんな事できんの!?ってのが凄いビックリする。
      • 職人芸すぎてついていけないと感じる事も
  • なんとか終えられるだろうか、その前にCSS3の初心者本に寄り道するかも

その他

  • 普段のプログラム書くのと、blog書くのってなんか垣根があるというか・・・
  • なんとか勉強したらそれがそのままblogに残るみたいな形にならないかなー
  • Mojoliciousの勉強とかやってると、オレオレCMS作りたくなったりする。
  • 今のところ、Perl , HTML5/CSS , Javascript ってのが勉強の柱。
    • Javascriptは仕事中の暇なときと思っているのだけど、なかなか着手できない事が多い。まとまった時間って必要だよなぁ。

業務に役立つPerl 第5章 ファイルとディレクトリを自由に操作する

基本的なファイルとディレクトリ操作

  • モジュールを利用していく
  • ファイルの指定には絶対パス

move

  • File::Copy モジュールを使うのが好ましい
  • 標準関数であるrenameはファイルシステムを超えた移動に対応していないため
use File::Copy 'move';  
my $from = 'temp1107_01.pl';  
my $to = '../';  
move($from,$to) or die qq{Can't move "$from" to "$to":$!};  

copy

use File::Copy 'copy';
my $from = 'temp1107_01.pl';
my $to = 'temp1107_03.pl';
copy($from,$to) or die qq{Can't copy "$from" to "$to":$!};

unlink(削除)

my $file = 'temp1107_03.pl';
unlink $file or die qq{Can't remove "$file":$!};

mkdir

  • 第二引数にパーミッションを指定する事ができる
  • 同名のディレクトリが存在すると失敗するので、ディレクトリがない事を確認してから作成
my $dir = "test";
unless ( -d $dir ) {
    mkdir ($dir,0755) or die qq{Can't create directory "$dir":$!};
}

rmdir

  • ディレクトリの中にファイルがある場合には削除できない。
    • File::Pathモジュールのrmtree関数を使用する
my $dir = "test";
rmdir $dir or die qq{Can't remove directory "$dir":$!};

mkpath 複数階層のディレクトリ作成

  • File::Pathモジュール
  • 第二引数には作成したディレクトリの一覧を表示するかどうかを指定できる
  • 第三引数にはパーミッションの指定ができる
use File::Path 'mkpath';
my $dir = 'dir1/dir2';
mkpath ($dir,1,0755);```

## rmtree 複数階層のディレクトリ削除
- 中にファイルが残っていても削除する

use File::Path 'rmtree'; my $dir = 'dir1/dir2'; rmtree $dir;

## glob,ディレクトリハンドル ファイル名一覧の取得
- glob関数では一部の日本語ファイル名の取得が出来ない事がある(!)
  - ぐぐると、Windows環境なんかでうまく動かないらしい
- opendir

## ファイル名に関する処理
- File::Basename 'basename'
  - 絶対パスから末尾のファイル名を取得
- File::Basename 'dirname' 
  - 絶対パスからディレクトリ名を取得
- File::Parse
  - ファイル名と絶対パスを取得可能だけど、パス名は最後に / が付くので注意
- File::Spec 'catfile'
  - ファイル名の連結をOSに応じた形で行う
  - メソッドで呼び出す

use File::Spec; my $dir = '/home/yours/log'; my $file = 'cpu.log'; my $file_abs = File::Spec->catfile($dir,$file); say $file_abs;

## $0 スクリプト名
## FindBin::Bin スクリプトのパス

use FindBin; say $FindBin::Bin

Head First JavaScript 第2版 第9章、第10章

ソートが苦手

  • というか、よく分からん・・・他の本に期待してページを進める
  • そういえば、Perlでもハッシュリファレンスのソートとか苦手だ

オブジェクト指向だ!(第10章)

  • この本では

    現実世界で喩えると、クラスは家の設計図であり、オブジェクトは家そのものです

  • オブジェクトクラスからオブジェクトインスタンスを作る

  • インスタンスはクラスから作られる

キーワードのthisはインスタンスによって所有されるプロパティやメソッドを設定するのに使います (中略)thisを使って設定したのでインスタンスメソッドを持っています。このためメソッドのコードがインスタンスごとに重複する訳です

  • わかる!無駄なことしてそうって分かる!
  • そこで

クラスが持つメソッドは、ひとつメソッドを共有して実行できます
クラスにメソッドを格納すると、ひとつのコピーをすべてのインスタンスが共有できます

  • ふむふむ。

JavaScriptのクラスはprototypeと呼ばれるかくれたオブジェクトのおかげで、実現する事が出来ます。

  • クラスにあるメソッドインスタンスが使い回す事が出来るので、メモリに優しい・・・
  • 繋がった感

  • 「続・はじめてのPerl 第2版」のオブジェクト指向のところは本当にわからず、他の本で良い解説に出会うまで待とう・・・ってな感じだった。

  • JavaScriptの方から理解の糸口つかめるとはなぁ。
  • 情報処理試験でももちろんオブジェクト指向についての設問はあったけど、あのときは本当の理解には遠かった。
    • でもまぁ、それでも合格することはできる。覚えてさえいれば。

Q.オブジェクト指向という語を見た事があります。どういう意味なのでしょうか?
A.(中略)一般には、オブジェクト指向プログラミング(OOP)はソフトウェアをオブジェクトから作成する事を意味します
(中略)オブジェクト指向の純粋主義者は、JavaScriptOOP言語を名乗る資格がないと主張しています。こうした神学論争には関わらないようにしましょう。どちらの主張も正しいので決着がつきません。

  • え、prototypeで組み込みのJavaScriptクラスも拡張できんのか・・・!

業務に役立つPerl 第4章 多次元データ構造を自由に扱おう

多次元データ構造

  • Perl最初の難関といわれるリファレンスと無名配列・無名ハッシュ
  • 当初は「そんなん使わんでも何とかなるだろ」とか思ってたけど、「配列の中に配列を入れられない」「ハッシュの中に配列を入れられない」などの制限がでてくるに及び、軍門に下った。
    • リファレンスを使わないで無理矢理組んでいた頃の自作プログラムを見ると、それはそれで貴重な気もする
    • 今の自分にはもう出来ない
  • Perl入学式の@papix校長曰く、「ひたすらやるしかない、やってれば分かる」
    • ほんとうにそうだった。ここだけは体育会系的にやるしかないなーという実感。
    • Perl入学式の練習問題でひたすら叩き込んだ。
  • あとは、自分の身近な事をデータ構造に直してみるとか

    • $東京都 = [ {name => 品川区,population => 370000} , {name => 渋谷区 , population => 200000}, ... ]
  • あと、YAPCAsia 2015のこれ。いきなりCの話が始まってびっくりしたけど、その後にちゃんとPerlでてくる。

  • 「変数は箱じゃない!」凄い分かりやすかった。

  • という状態でこの第4章をみてると、「うむ、わかる」となるけど、全くの初心者だった頃にこれを見ても挫折するだろうな、って思う。

    • ほんと取っ付きにくいよなー

業務に役立つPerl 第3章

Sublime Perl Tidyの偉大さ

  • Perl入学式(2013年)でおすすめ環境・エディタとして紹介されていた「sublime text2」には、SublimePerlTidy という追加機能がある
  • これのおかげで、形についてはPerl Best Practice通りになってる
  • 早い時点でこれを入れることができて、本当にラッキーだった

PertTidy以外の部分

  • strict & warnings は有効に
  • レキシカル変数を使う
  • デフォルト変数($_)は可読性下げるので使わない
  • 命名規則
    • レキシカル変数の命名規則は小文字とアンダーバー
    • パッケージ変数の命名規則は大文字とアンダーバー
    • サブルーチンの命名規則は小文字とアンダーバー
      • 動詞 + 名詞の形式にすると分かりやすい
  • do 〜 while は使わない
  • redo,gotoも使わない
  • foreachではレキシカル変数を使う
  • open

    • 第一引数はレキシカル変数にする
    • 3つの引数を使うやり方で
    • 開けなかったときの例外処理も書いておく

    ```perl open $fh , '<' , '$log_file' or die "Cannnot open file \"$log_file\":$!";

  • サブルーチンのプロトタイプは使わない

  • コメントは処理の説明を書く
  • 不必要なモジュールは読み込まない
  • インポートする関数を明示する
  • 日本語などのマルチ梅友次を使うときにはEncodeモジュールを使う
  • utf8形式で保存し、utf8プラグマをつける
  • エラーは例外処理をつかう
    • evalブロックで囲う
    • エラーが発生すると@_にエラーメッセージが格納される