nkc+

先日、『初めて文字コードで』に書いた文字コード変換で、どうしても QKC っぽい感じで変換をしたいので、ちょっと考えてから、もう公開されていない nkc のコードを読んでいた。

ruby という言語は、実は今まで一回も触ったことがないのだけど、まあ見て何も分からないというわけでもない。見ると、日本語コードの判定のために専用のライブラリを書いているのだが……そうか、これって ruby1.8 時代のコードなんだよな、と気付いた。ruby はかつて Perl よりも日本語処理においてパワフルでなかった時期があって、その頃に書かれたこのコードは、検出し誤りを防ぐために、検出部を自力で書いている。そして変換は iconv で行っている……のだが、今は、ruby のモジュールで新しい nkf の機能がフルに使えるので、こんなことをしなくてもいいかもしれない。

現在の nkf というのは、実は結構強力で、--guess オプションを使うと簡単に文字列のエンコーディングを判定できる。これを使わない手はない……ということで、独自ライブラリと iconv を使うところを nkf で済ませるように書き換える。まあね、ruby いじるの初めてでも、これ位はいけるんですよ、ええ……

などとやっていたのだが、1箇所で思いっきりハマった。改行コードの変換に gsub を使って、

body = body.gsub(/(\r\n|\r|\n)/) { newline }
……などと書いていたのだけど、場合によってここでエラーが出てしまう。んー???と思いつつ挙動を探ると、どうも body に ISO-2022-JP の文字列が入っているとこうなる、らしい。うーん???……などと考えつつ、30分程を空費してしまう。

おそらく ruby に慣れた方は、ここまで読んで「はいはい」と気付かれたことだろう。僕は、ruby が ISO-2022-JP の文字列操作を直接できないことを、今日まで知らなかったのだ。そりゃそうだ。ruby のスクリプト書くのは今日が初めてなんだから。しかしなあ。

え。で、どうしたか、って?

if to == "ISO-2022-JP" then
body = NKF.nkf("-m0 --cp932 --oc=UTF-8", body)
body = body.gsub(/(\r\n|\r|\n)/) { newline }
body = NKF.nkf("-m0 --cp932 --oc=ISO-2022-JP", body)
else
body = body.gsub(/(\r\n|\r|\n)/) { newline }
end
……まあこれで、QKC に UTF-8 拡張をしたのと同等の処理ができるようにはなった。なったけれど、これは、美しくない。ダメダメだ。あ゛ー。

【後記】後で気付いて、gsub を使わず NKF で変換するように変更。

  if newline then
case newline
when "\r\n"
print " (CR+LF)"
optio = "-m0 -x -Lw -c --ic="+to+" --oc="+to
when "\r"
print " (CR)"
optio = "-m0 -x -Lm --ic="+to+" --oc="+to
when "\n"
print " (LF)"
optio = "-m0 -x -Lu -d --ic="+to+" --oc="+to
end
body = NKF.nkf(optio, body)
end
……こんな感じ。こういう発想が出て来ないという時点でダメダメだ。頭が固くなってる。

……などとやって、夕食後、手持ちのテキストで変換を試していて、再びドツボにはまる。文字コード検出で不具合が出てしまうのだ。

CODES = {
NKF::JIS => "ISO-2022-JP",
NKF::EUC => "EUC-JP",
NKF::SJIS => "Shift_JIS",
NKF::UTF8 => "UTF-8",
NKF::ASCII => "ASCII",
NKF::BINARY => "BINARY",
NKF::UNKNOWN => "UNKNOWN",
}
(中略)
from = CODES.fetch NKF.guess(body)
のようにしてコード種別の検出を行っていたのだけど、
/usr/local/bin/nkc:96:in `fetch': key not found: #<Encoding:Windows-31J> (KeyError)
と怒られる。うーん……と、NKF の仕様を読んだり、ネットの海を彷徨ったりした挙句、
CODES = {
NKF::JIS => "ISO-2022-JP",
NKF::EUC => "EUC-JP",
NKF::SJIS => "Shift_JIS",
NKF::UTF8 => "UTF-8",
NKF::ASCII => "ASCII",
NKF::BINARY => "BINARY",
NKF::UNKNOWN => "UNKNOWN",
Encoding::EUCJP_MS => "EUC-JP",
Encoding::CP51932 => "EUC-JP",
Encoding::WINDOWS_31J => "Shift_JIS",
}
(中略)
from = CODES.fetch NKF.guess(body)
とする。--CP932 オプションも、不要な部分は消してしまう。これで……今度は OK ね。はぁ。

うーむ。やはり perl で書き換えた方が早かったような気がする。僕は ruby のエヴァンジェリストでも何でもないしなあ。

【後記】後でちょっと考えて、半角カナの処理も付け加える。まあ、この辺にしておこう。いわゆる「外字」のことまでケアするとなると面倒な話になりそうだしなあ……はあ。


2011/08/19(Fri) 19:11:24 | コンピュータ&インターネット
Tittle: Name:

Profile

T.T.Ueda
Tamotsu Thomas UEDA

茨城県水戸市生まれ。

横山大観がかつて学んだ小学校から、旧水戸城址にある中学、高校と進学。この頃から音楽を趣味とするようになる。大学は、学部→修士→博士の各課程に在籍し、某省傘下の研究所に就職、その2ヵ月後に学位を授与される(こういう経緯ですが最終学歴は博士課程「修了」です)。職場の隣の小学校で起こった惨劇は未だに心に深く傷を残している。

その後某自動車関連会社の研究法人で国の研究プロジェクトに参画、プロジェクト終了後は数年の彷徨を経て、某所で教育関連業務に従事。

New Entries

Comment

Categories

Archives(902)

Link

Search

Free

e-mail address:
e-mail address