帯に短したすきに長し

講演準備でずっと動けなかったので、データの分析を武田君に頼みっぱなしにしていたが、自分でいろいろやってみたくなった。武田君は、LSMのUNIX mboxをrubyのmailreadを使って処理していると聞いたので、週末いろいろ試してみた。やりたいことは、mboxの6507件のデータから興味あるフィールドを(あとの加工用に)Excelに格納するという単純な内容だ。

試しに、"^Subject: "でgrepをかけてみると、Thunderbirdが表示する件数よりもずいぶんと多い結果がヒットする。これは何故かというとメールの本文の中で他の人のメッセージをそのまま引用しているものがあるからだろう。

mailreadはコンパクトで手頃で処理も速いのだけれど、Subjectの内容が複数行に分かれていると最初の行の値しか拾わないようだ。そこでTmailというのを探してきた。苦労しながらなんとか使えるようにできたけれども、TmailはSubjectをちゃんと拾ってくれるが、Message-IDでカウントした数より多くのSubjectを返してくる。どうもmboxを正しく解析できていないような気がする。

Thunderbirdがスレッドを表示できているということは、(当然ながら)mboxを正しく解析できているということだから、その内容をexportするようなadonを作っている人がいないかな?」と思って、adonを探したところいくつか見つかったが、一番動きそうなものをインストールして試してみたら、お粗末な結果でこれはあきらめた。

「mboxを解析(parse)して、そこに含まれているフィールドを拾うという処理はどう考えても汎用的でニーズがあるだろうからPerlなら枯れてちゃんと動くモジュールがあるだろう」と思い、久々にPerlを使ってみることにした。調べてみたところいくつかモジュールは見つかったが、残念なことに定番、決定版はないようだ。

いくつかのモジュールで挫折を繰り返してから、最終的にはMail::Box::Managerというものを見つけたが、ドキュメントや使用例が少なくて苦労した。

#!/usr/bin/perl

use Mail::Box::Manager;

my $mgr = Mail::Box::Manager->new;
my $inbox = $mgr->open('lsm-escaped');
die unless defined $inbox;

my $count = 0;

foreach my $msg ($inbox->messages)
{
$count = $count + 1;

print $count, '@@@',
$msg->head->get('message-id'), "@@@", $msg->head->get('from'), '@@@',
$msg->head->get('subject'), "@@@", $msg->head->get('x-from'), '@@@',
$msg->head->get('date'), "\n";
}

単に興味があるフィールドの値を出力しているだけだが、データのセパレータとして'@@@'を入れているのは、上記の出力をいったんtabをspaceに変換させて、それから'@@@'をtabにしようとしているからだ(LSMのデータを見ていて、Subjectの中にやまほどtabが含まれているのがわかった)。そのようにして得られたデータをExcelの外部データとして読み込ませると、きれいに収まった。