Perlのコーディングからサーバ構築等で覚えてると便利な知識を残してます。
勘違いしている箇所等が間違いなくあると思うのでその際はメールフォーム等を通して知らせて頂ければ…
ある程度コーディングしてると自分のライブラリみたいなものが出来上がってくるものです。
勿論Perlに関しても例外ではなく、これまで自分がコーディングで使用していた手法でも載せておこうかなと。
その他にも色々なサイトで見つけた効率的な手法についても書き記していこうかと。
Perl講座-Smartにある通りファイル入出力記号は意外と多い。
自分の使用している手法では新規作成に[ > filename ]、書換時に[ +< filename ]、削除時は unlink("./filename");
新規作成
open(IN,">$filename"); close(IN);
# この前に新規作成でファイルを作成しておかないとエラーになる。
open(IN,"+<$filename") or &error("Can't open file"); flock(IN,2); seek(IN,0,0); print IN "test"; truncate(IN,tell(IN)); close(IN);
unlink("./$filename");
配布サイトではflockを使えない環境でも制御させるために他の汎用的な手法で制御する場合もあるが
使用できる環境であるならflockを使用したほうが簡単なのでおすすめ。
ただしflockでも完全なファイル保護は出来ないので不安ならデータベースに移行する方が得策かもしれない。
参考サイトPerlの排他制御
# こちらがよく使う手法 open(OUT, "+< $datafile"); # 読み書きモードで開く flock(OUT, 2); # ロック確認。ロック seek(OUT, 0, 0); # ファイルポインタを先頭にセット print OUT "$data\n"; # 書き込む truncate(OUT, tell(OUT)); # ファイルサイズを書き込んだサイズにする close(OUT); # closeすれば自動でロック解除
参考サイトによると下の方が遅いらしい
# 遅い方 open(OUT, "+< $datafile"); # 読み書きモードで開く flock(OUT, 2); # ロック確認。ロック truncate(OUT, 0); # ファイルサイズを0バイトにする seek(OUT, 0, 0); # ファイルポインタを先頭にセット print OUT "$data\n"; # 書き込む close(OUT); # closeすれば自動でロック解除
環境に左右される可能性も否定できないので自分の環境でもテストしてみた。
テストファイルはこちら(speedtest0.txt 拡張子を.txtから.cgiに変更)
テスト環境:CPU i7 920@1.60GHz固定、HDD Hitachi 500GB、OS Vista 64bit、Apache2.2 + Active Perl 5.8.9
実行結果
Benchmark: timing 5000 iterations of TEST1, TEST2... TEST1: 4 wallclock secs ( 0.25 usr + 0.78 sys = 1.03 CPU) @ 4854.37/s (n=5000) TEST2: 5 wallclock secs ( 0.33 usr + 1.33 sys = 1.65 CPU) @ 3024.80/s (n=5000)
技術的な解説は出来ないが恐らく truncate で切り落とす量が少ないほど速いと解釈しておこう。憶測の域を出ないが…
Perlでの多次元配列は他の言語に比べて少々扱い難い。
慣れの問題なのでエラーを起こしながら仕様を理解するのが一番早い方法だと思う。
ほんの一例ではあるけどここでPerlでの多次元配列の動作を確認してみた。
#!/usr/local/bin/perl @a = (["a","b","c","d"], ["e","f","g","h"], ["i","j","k","l"]); @{$b[0]} = (1,2,3); @b[1..3] = (4,5,6); @buf = &ar(@a); print "Content-type: text/html\n\n"; print "@a = @a\n"; print '@aの要素数 ='.@a."\n"; print "@{$a[0]} = @{$a[0]}\n"; print "@buf = @buf\n"; print "@b=@b"; sub ar { return @{$_[2]}; }
# 動作結果 @a = ARRAY(0xeaffc) ARRAY(0x1b77814) ARRAY(0x1b77a44) @aの要素数 =3 @{$a[0]} = a b c d @buf = i j k l @b=ARRAY(0x1b77ab4) 4 5 6
要点さえ抑えればそんなに扱いに苦労するということはないはず。
以下にまとめると
@a = ([1,2,3],[4,5,6]);のように丸括弧()の中で更に角括弧[]で囲みコンマで区切る。
特定の位置に作成したい場合は@{$a[3]} = (1,2,3);と@の次を波括弧{}で囲む必要がある。
※この時に@{$a[3]} = ([1,2,3]);とすると実質三次元配列となるので値を取り出す場合は@{$a[3][0]}とする。
通常二次元配列で値を取り出す場合は@{$a[0]}と作成時と同じように@の次を波括弧{}で囲む。
通常二次元配列を波括弧{}で囲まずに使用するとアドレスしか取り出せない。
※動作結果にもある通り要素数を取り出す事は可能だが全要素数ではなく一次元での要素数しか返さない
二次元配列を引数としてルーチンに渡すとルーチン内でも多次元配列と同じ扱いが必要になる。
特にゲームなどの開発を行っている段階だと追加要素も出てくるはずなので重要なルーチンでは汎用性を持たせるために多次元で渡すのもありかなと。
Copyright (C) 2010 幻想空域. All Rights Reserved.