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

アルパカDiary Pro

はてなブログProではありません

初めてのPerlを読み返す 16−17章 単純DB・上級向け

Perl 勉強

初めてのPerl
初めてのPerl
posted with amazlet at 09.04.05
ランダル・L. シュワルツ トム フェニックス
オライリージャパン
売り上げランキング: 34126


この記事のスタンスはこちら

16章 単純なデータベース*1

  • DBMハッシュとはDBMファイルのこと。ハッシュを使うようにしてファイル内容を操作できる。
  • DBMハッシュのオープン/使用/クローズ
# DBMハッシュのオープン
# 第三引数の「0644」は、DBMファイルが存在しない場合に新規ファイルを作成するときのパーミッション。
dbmopen(%DATA, "my_db", 0644)
  or die "Cannot create my_db: $!";

# 使用
$DATA{"aaa"} = "123";

# DBMハッシュをスキャンする場合はeach関数を使用した方がメモリを使わなくて済む
while (my($key, $value)= each(%DATA){
  print "$key=>$value\n";
}

# クローズ
dbmclose(%DATA);
  • pack と unpack を使ってデータを加工する。
# c => char型(1バイト)
# s => short型(2バイト)
# l => long型(4バイト)
my $buf = pack("c s l",31, 4159, 265359);
  • 固定長ランダムアクセスデータベース
    • 1.ファイルを読み書き両用でオープン
    • 2.ファイル内で、任意の位置に移動
    • 3.指定したバイト数だけデータを読み込む(改行文字ではない)
    • 4.データを固定長で書き込む
# ex.レコードのフォーマット
#  名前:30文字
#  年齢:1バイト整数
#  国数英の点数:1バイト整数×3
#    フォーマット:「a30 C C3」=34バイト

# オープン
open (DB, "+<fred");

# レコードn行の先頭にシーク
seek(DB, 34 * $n, 0);

# 読み込み
my $buf;
my $record = read(DB, $buf, 34);
# アンパック
my ($name, $age, $score1, $score2, $score3)
 = unpack "a40 C C3", $buf;

# レコード書き込み
print DB pack("a40 C C3", 
  $name, $age, $score1, $score2, $score3);

# クローズ
close (DB);
  • 可変長ランダムアクセスデータベース
    • 基本的には「必要な変更を加えられた新しいファイルを作成」する。
    • 可変長の例(date???.datというファイルを取得し、中身の「Date: 日付」という項目を更新する)
chomp(my $date = `date`);
@ARGV = "date*.dat" or die "no file found";

# 特殊変数「$^I」に値を代入すると、ダイヤモンド演算子の挙動を変更する!
#  動作の流れ
#   1. ダイヤモンド演算子は、いつも通りファイルをオープンする
#   2. オープンしたファイルをすぐにリネームする(「入力ファイル名」+「$^Iに設定した文字列」)
#   3. printすると、出力先はデフォルトで「入力ファイル名」になる(新しいファイルに書き込まれる)
$^I = ".bak";

while (<>){
  s/^Date:.*/Date: $date/;
  print;
}
$ perl -p -i.bak -w -e 'chomp(my $date = `date`); s/^Date:.*/Date: $date/' date*.dat

-i  $^Iと同じ
-p  このようなことを行う => while(<>) { print; }
-e  実行するperlスクリプトを記述

17章 上級テクニック

  • evalでエラーをトラップできる(try〜catch的な)
eval {
  $barney = $fred / $dino;
};
if($@){
  # エラー時
  print "An Error Occurred ($@), continuing\n";
}
  • grepでリストから要素を選び出す
foreach (1..1000){
  push @odd_numbers, $_ if $_ %2 ;
}
# 上記foreachと同じ事
my @odd_numbers = grep {$_ % 2} 1..1000;
  • mapでリストを変換する
# 「big_money」メソッドで、変換した結果をformatted_dataに格納したい
foreach (@data){
  push @formatted_data, &big_money($_);
}
# 上記foreachと同じ事
my @formatted_data = map { &big_money($_) } @data
  • 「欲張りでない量指定子について」…はまだ勉強中。というかよくわからない。
  • スライスの例
# statが返すリストの「9番目」を取得
my $mtime = (stat $some_file)[9];
# 「splitvar」の結果リストから「0番目を$aaa」に、「4番目を$eee」に格納する
my ($aaa, $eee) = (split /:/, $splitvar)[0, 4]
  • 配列スライス/ハッシュスライスの例
# 配列スライス
my @array = @orgs[6, 3, 0, 2, 6];

# ハッシュスライス
my @array = @score{ qw/ barney fred dino / };
# 上記はこれと同じ
my @array = ($score{"barney"}, $score{"fred"}, $score{"dino"});


後半ちょっと難しくてまだモヤモヤしてる部分もあります。うーん


というわけで、初めてのPerl読み返しは今回で終わりです。
いや全然わかってなかったなーというのが本音。
まだまだPerlレベル2くらいです><
http://d.hatena.ne.jp/naoya/20050809/1123563794
続・初めてのPerlも読みたくなってしまったので
明日ジュンク堂で買ってこようかな

続・初めてのPerl 改訂版
Randal L. Schwartz brian d foy Tom Phoenix 吉川 英興 伊藤 直也 田中 慎司 株式会社ロングテール/長尾 高弘
オライリー・ジャパン
売り上げランキング: 141655

*1:以下引用を含みます