塩茶コンバータふたたび

UTF-8で出力できるように書き直し。もちろんShift_JIS*1のままで書き出すことも可能なようにしてあります。けっこう手間取りました。前に書き上げた部分にも潜在的なバグが潜んでたりしたので、それも全部修正。

my $l = shift;
for ($l) {
    s/>/>/g;
    s/&lt;/</g;
    s/&quot;/"/g;
    s/&amp;/&/g;
    s|</b>||g;
}
return $l;

順序がおかしいことと、Aタグの削除を忘れている点で、上のコードは間違いです。正しくは、以下のように

my $l = shift;
for ($l) {
    s|</b>||g;
    s|</?a.*?>||g;
    s/&gt;/>/g;
    s/&lt;/</g;
    s/&quot;/"/g;
    s/&amp;/&/g;
}
return $l;

まずBタグの終了タグと、Aタグの削除*2。それから&gt;などを変換しないといけません。そうしないと、まず実際にはないと思うけど、例えば

&lt;/b&gt;

なんて文字があったときにあやまって削除してしまいます。
HTML::Entitiesを使わないのは、Shift_JISで出力するときには上の4つだけを変換したいから。UTF-8で出力するときは、&HTML::Entities::decode_entitiesを使ってます。
ちなみに、1個の変数に対してforeachループを使っているのは、主題化*3というテクニック。これをしないで書くと以下のようになって、表現が冗長になります。上の例のほうが読みやすいでしょ?

my $l = shift;
$l =~ s|</b>||g;
$l =~ s|</?a.*?>||g;
$l =~ s/&gt;/>/g;
$l =~ s/&lt;/</g;
$l =~ s/&quot;/"/g;
$l =~ s/&amp;/&/g;
return $l;

あとはEncodeモジュールを使って文字コードの変換ですね。入力はShift_JIS、出力はShift_JISUTF-8。ファイルフォーマットの変換は完成しているので、文字コードの変換処理を書き加えるだけで完成です。まあ、それだけのことをするのにだいぶ時間をかけてしまったんですけどね。あまりEncodeを使ったことがないので、きちんと変換させるのに一苦労しました。Shift_JISとCP932の違いとか。まあ、きちんと完成したので問題ないですが。

*1:厳密には違います。元ファイルがCP932なので、書き出すのもCP932です。以下、今日の日記に出てくるShift_JISは、正確にはCP932のことです。

*2:仕様から、他のタグは出てこないので無視してます。だからこのコードは汎用的じゃないですね。汎用的に書くなら、HTMLのパーサを利用してテキスト部分だけ抜き出すのがいいのかな。

*3:topicalization