2006-09-24

wzmbox.py

WZ MAIL で「標準 MBOX」形式にエクスポートしたメールボックスを、Mozilla Thunderbird などで使われている mbox 形式に変換するスクリプト。

操作例。

  1. WZ MAIL でエクスポートしたいフォルダを選択し、[フォルダ]-[エクスポート]。
  2. [エクスポート] ダイアログで [形式] を「標準MBOX」にして保存する。ここでは wzmail.mbox として保存したとする。
  3. コマンドラインから wzmbox.py wzmail.mbox > wzmail する。結果は標準出力に出るのでリダイレクトして保存している。
  4. Thunderbird のメール保存フォルダ([アカウント設定] の [メールの保存先] に保存先フォルダのパスが表示されている)を開き、前項で変換したファイル (wzmail) をそこに移動する(拡張子はつけない)。この作業の間は Thunderbird は起動していないこと。
  5. Thunderbird を起動させると変換したメールボックスが認識されているはず。

変換速度は遅いです。-v オプションでも付けてのんびり待ってね。

WZ MAIL でエクスポートしたメールボックスは、SubjectFrom がデコードされた状態で格納されてしまってるし、Content-Type: text/plain; charset=iso-2022-jp とか書いてあってもエンコーディングは Shift_JIS になってるしで、あれでまともにインポートできるメーラーはないんじゃないかという気がします。

けっきょくスクリプトでは、Content-Type の情報から元のメッセージを再構築するという方法を取らざるをえなかった(遅いのはそのせい)。なので、ヘッダの出現順や表現形式などは変換前と同じではありません。どうせ受信時そのままのはもはや再現できないんだから、まあ仕方ないよ。

自分のメールボックスでテストしただけなので、かならずしもあなたの環境ですべてのメールボックスをうまく変換できるとは限りません。あしからず。

オライリー 乗り換え WZ MAIL

2006-09-21

ftpsite.pl にまつわる雑談の続き。

本当のことをいうと、ネットワークにパスワードを平文で流す FTP は時代遅れなので使わないほうがいいんですよね。ウェブサイトの更新にローカルとの同期をしたいというのであれば rsync とか Unison などを使ってするほうがいい。とくに Unison は便利そうなので移行したいのです。

とはいっても、SSH でログインできたり sftp が使えたりするホスティングサービスというのはまだ一般的ではないんじゃないかと思うし(調べてませんが)、まだ置いておいてもいいか。さくらインターネットは先進的すぎるんだ。

FTP クライアントというのは、いまはすっかり廃れてしまったんじゃないでしょうか。パーソナルなページならいまやプロバイダがブログのためのスペースを用意してるから、それを使えばたいていのことはできてしまう。日記はもちろん、写真を載せたい人にも使えるし、コメント機能があるからコミュニケーションツールも兼ねている(これはスパムで虫の息ですが)。「ほーむぺーじをつくるには」みたいな記事で、FTP クライアントをインストールさせたり Perl の CGI を書かせて「とっても簡単!」とか虚偽の記載を並べていた欺瞞の時代はなんだったのだろう、とか、思います。

そう考えるとウェブも少しは使いやすいものになっているのかもしれません。ブログの偉かったところはトラックバックとか RSS なんかじゃなくて人を FTP から解放したところですよね。

ウェブログもコミュニケーションスペースもないサイトを FTP で更新している自分ですけど。

Free Podcasts from National Geographic

ナショナル・ジオグラフィックのポッドキャスト。ビデオ・ポッドキャストがたくさんある。

Audio and Video Podcasts from National Geographic
http://www.nationalgeographic.com/podcasts/

「Atmosphere」が新機軸すぎです。

2006-09-13

(追記あり。)

問い:
別のところで定義されている文字 $A, $B があったとする。文字列 $s 中にある $A をすべて $B に置き換えたい。Perl でこれを処理するにはどう書けばよいでしょう。

$A, $B というのはようするにグローバル変数です。

さて、$A, $B が文字なので、文字を入れ替える tr 演算子を使うだろう、と考えるわけです。

$s =‾ tr/$A/$B/;

ブー。これはうまくいかない。tr 演算子は変数展開をしない。なんなんだこれは。$s =‾ tr/X/Y/; と書いて XXXYYY にすることはできるけど、$X = "X"; $Y = "Y"; tr/$X/$Y/; はできない。どうするのかというと、こうしろと。

eval "¥$s =‾ tr/$A/$B/;";

ありえん。eval て。個人的には eval というのは最後の手段的なものだと思ってましたが。デバッグできないし。しかもこれは正しく動かない。$A‘/’$B‘Y’ だったらどうなりますか。eval されるのは “$s =‾ tr///Y/;” というわけでエラーになります。

なので事前に文字をエスケープする必要があります。$A, $B はグローバル変数なので勝手に置換してしまうわけにはいかないので、ローカルにコピーして使います。

my $a;
my $b;
($a = $A) =‾ s/(¥¥|¥/)/¥¥$1/g;
($b = $B) =‾ s/(¥¥|¥/)/¥¥$1/g;
eval "¥$s =‾ tr/$a/$b/;";

これでいちおう正解(のはず)。たのしいね。

こんなのやってられないので正規表現置換することにします。s 演算子は変数展開もしてくれるし。

$s =‾ s/$A/$B/g;

もちろんこれもアウト。今回は $A ないし $B‘¥’ だと正規表現のメタ文字として解釈されておかしなことになります。というわけでエスケープ。今回も $A, $B はローカルにコピーします。

my $a;
my $b;
($a = $A) =‾ s/¥¥/¥¥¥¥/g;
($b = $B) =‾ s/¥¥/¥¥¥¥/g;
$s =‾ s/$a/$b/g;

これで正解(のはず)。ぜんぜん行数減ってない。

追記。

上のコードは間違っていました。$B‘¥’ のときに間違った結果になります。正しくは以下のようにする必要がある。

my $a;
($a = $A) =‾ s/¥¥/¥¥¥¥/g;
$s =‾ s/$a/$B/g;
$s;

エスケープ処理するのは $A のほうだけでいい。置換文字列のほうは正規表現じゃないからか。なんか正規表現リテラルがあるとかえって混乱するな……。

‘X’‘¥’ に置換。 ‘¥’‘X’ に置換。
直接指定 変数を経由 直接指定 変数を経由
Perl
$s =‾ s/X/¥¥/;
$a = "X";
$b = "¥¥";
$s =‾ s/$a/$b/;
$s =‾ s/¥¥/X/;
$a = "¥¥¥¥";
$b = "X";
$s =‾ s/$a/$b/;
Python
re.sub('X', '¥¥', s)
a = 'X'
b = '¥¥'
re.sub(a, b, s)
re.sub('¥¥¥¥', 'X', s)
a = '¥¥¥¥'
b = 'X'
re.sub(a, b, s)
TX-C(笑)
regular(s, "X", "¥¥", 0);
a = "X";
b = "¥¥";
regular(s, a, b, 0);
regular(s, "¥¥¥¥", "X", 0);
a = "¥¥¥¥";
b = "X";
regular(s, a, b, 0);

↑これでよい? 強調部分の非対称性が罠か。

さて、Perl で正規表現のエスケープに使うメタ文字、¥Q, ¥E中村さんから教えてもらいました。

$s =‾ s/¥Q$A¥E/$B/g;

ありがとうございました。これがどうも Perl での「いちばん正しい」書きかたみたいですね。

じつはもうひとつ、1行で書けるのも考えました。

join '', map { $_ eq $A ? $B : $_ } split //, $s;

でもこれはかなり遅いみたいです。それにべつにわかりやすいわけでもありませんし。

ところでこの処理を Python で書くとこうなります。(べつに Python でなくてもまともな文字列操作メソッドがある言語ならおんなじでしょうけど。)

s.replace(A, B)

あと Perl でもっと簡単に書ける方法をご存知の方は教えていただけるとありがたいです(というか単純な replace はないのでしょうか)。

2006-09-11

雑談。

なんで Perl の Getopt なんかを調べたかというと、ftpsite.pl に手を入れているのでした。忙しいので一日にほんの少しずつしか進めてないけど、息抜きです。

もう二年以上も前に書いたきりのスクリプト。いま見ると冗談抜きで「これはひどい」といいたくなるような書き方だ。恥ずい。書いていた当時は大真面目だったはずなのですが。これは二年間で成長しているということなのか、それともたんに書く能力がないだけなのか……。

正直なところもう Perl は書きたくなかったので、うっかり ftpsite.py に取り掛かりかねない勢いだったのですが、ここはあえて思いとどまることに。また、書いたのがもう二年前ということで「最初から書き直したほうがいいかも」という誘惑も強かったのですが、それも制止。Perl のまま、古いコードに手を入れる方式で改良してみることにしました。なんとなく、たまにそういうこともしないと技術が向上しないような気がしたので……。

ひさしぶりに書く Perl。もうセミコロン忘れる忘れる。print 文の末尾に "¥n" を忘れる忘れる。

でもなんとかリファクタっぽいことができました。旧コードから始めたけど、その面影は現在はほとんどなくなっている。途中あたりから面白くなってきますね。やっぱり最初から書き直さなくてよかったと思いました。

あと Python がいかにまともかを思い知りました。

2006-08-27

更新情報

Perl での Getopt::Long モジュールの使い方についてのメモ、「Perl スクリプトでのコマンドラインオプション処理」を書きました。Getopt、Python では使ってたのですが、Perl のほうはいまいちやり方がわかってなかったので。

Python の getopt モジュールはドキュメントの「getopt — コマンドラインオプションのパーザ」がわかりやすいです。

こうして両者を比べてみると、同じ機能でも実装にその言語らしさが如実に出ていておもしろい。暗黙的な Perl と明示的な Python。–nohoge のサポートなんかは Python プログラマからしたら変態的に見えるだろうし、短縮形のオプションや型変換まで明示的にやらなければいけない getopt 関数は Perl プログラマからすると融通が利かないということになるのでしょうか。

Alt + Home

先日の某所オフにて、ThinkPad X60s を中村さんに見せてもらっていて、なにげなく「(キーボードの)右Alt がないと、Alt + Home しにくいですね」と言ったら「???」という反応をされてしまった。ウェブブラウザで Alt + Home(ホームに戻る)、あんまり知られてないのかしらん。

僕はブラウザのホームを Google にしているのですが、そうしてブラウズ中に検索したいことができたら「Alt + Home を押す」→「検索語入れて検索」というのが日常になっていたのです。で、右 Alt があったら Alt + Home が右手だけでできるじゃないですか(左 Alt + Home も同じくらい使うけど)。

あんまり有名じゃないみたいですが、特定のページに一跳びできるキーボードアクションなんて貴重ですよ、ということで、うまい使い方を思いつく人もいるかと思って書いてみました。