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 のエヴァンジェリストでも何でもないしなあ。

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


LaTeX で用紙サイズがおかしくなるときは

実は、TeX Live 2010 以降に、妙な問題に悩まされていた。LaTeX の文書内でハイパーリンクを張るための hyperref というマクロがあるのだけど、これを使うと用紙のサイズがおかしくなってしまうのである。

具体的には、A4 よりもやや横に大きなサイズにタイプセットされてしまう。どうも、用紙サイズがレターサイズになってしまっているようで、\documentclass の引数に用紙サイズを a4paper 等と明示(って、普通明示するんだけど)しても治らない。困った挙句に、

\usepackage[a4paper]{geometry}
と書いて押し込んでいたのだけど、こう書くと、文字のポイント数が小さくなってしまう。うーん……と、困っていたのだった。

で、何となくググっていたところ、『4403 is written(終了しました)』2010年2月 7日 15:15 に辿りついたのだった。なになに……

ポイントはPDFしおりの文字化け対策と用紙サイズが適切に認識されない問題への対応です.PDFのしおり文字化け問題は昔のエントリーを見てください.documentclassのオプションにpapersizeを付けてやると用紙サイズがdvipsやdvioutに送られます.詳しくはマニュアルを読んでください.参考にしたのはこの情報.だいぶ昔からあった問題みたい・・・.何故,オレが博論執筆していたときは問題が具現化しなかったんだろう??
PDF のしおりが文字化けするのは既に分かっていて、これには対策を施していたのだけど、「documentclassのオプションにpapersize」というのは不明にして知らなかった。これを試すと……嘘のように簡単に、hyperref に関する問題が解決したではないか!

やはり、思い出したときにはマニュアルには目を通さなければダメだなあ、と、今更ながらに思い知らされたのであった。

W32TeX

基本的に、僕は音楽関連の作業をするとき以外は Microsoft Windows を立ち上げることはない。勿論、基本的な UNIX 系のコマンドセットを入れ、日本語変換も SKKIME で行うようにして、perl や ruby も使えるような環境を整えているのだけど、無理して Windows を使う理由がないのだ。

しかし、僕の Windows のシステムで、アンチウイルスソフトを更新する時期が近付いているので、それに合わせてメンテをしているうちに、ちょっと入れてみようかなあ、と、ふと思ったのだった。最初は TeX Live にしようと思っていたのだが、Windows 版の TeX Live は未だに 64 bit 化されていない。それだったら、角藤氏の W32TeX を入れるのとあまり差がない(まあ TeX Live は tlmgr で常に最新の状態に維持できる、というメリットはあるのだけれど)。ということで、W32TeX を導入することにした。

基本的な導入手順は、角藤氏のページに書かれている通りである。彼のアーカイブは RING server 等に置かれているので、wget 等を利用してあるディレクトリにごそっと取っておいて、インストールを実行するだけである。

フォント埋め込み用のファイルや、先日導入した emath なども、Linux から NTFS パーティションをマウントして、全て C:\w32tex\share\texmf-local に流し込む。後は TeX Live 同様に、texhash で ls-R データベースを更新するだけである。

タイプセットしてみると、Linux 上で行うのと何ら変わらない。まあ、こんなものでしょうねえ。しかし……だったら 64 bit native の TeX Live を Linux で使う方がいいわけで、やはり Windows を使うことには何もメリットがないのであった……

初めて文字コードで

先日導入した emath のテストのために、tDB 氏の書かれたドキュメントをいくつか LaTeX でタイプセットしていたのだが、そのままでは変換できないものがいくつかあった。

TeX Live の platex は、iconvでプリプロセスするような仕様になっているので、.tex ファイルの文字コードが何であっても、通常は問題が生じないはずである。事実、僕の場合も、JIS と UTF-8 が混在する環境で使っているのだが、今迄これでトラブったことはない。しかーし、今回のファイルはいわゆるシフト JIS だったので、初めてこれを疑ったのだった。

昔から、テキストファイルを複数の環境で扱う人間にとって、この文字コードの問題は悩みのタネだった。伝統的に、UNIX 等のシステム上では EUC-jp か JIS を使うことが多かったわけだけど、パソコンという代物は皆シフト JIS が一般的であった。昔は、自宅のパソコンを常時接続環境で使っている人などまず存在しなかったので、家と学校 / 職場で作業を行う場合、これらの間で文字コードを変換することは不可避だった。

それだけならまだよかったのだけど、これに加えて、UNIX 系のシステムと Microsoft 系のシステムでは、テキストファイルにおける改行を示すコードが違っていた。前者は LF、後者は CR + LF というコードで改行を示していたのだけど、丁度僕が大学に入る頃から出てきた Mac では、困ったことにこれを CR で表わしていた。つまり、

文字コード 改行コード
UNIX EUC-jp / JIS LF
Microsoft Shift-JIS CR + LF
Mac(〜 OS9) Shift-JIS CR
……という、ややこしい状況になっていたわけだ。

こういう状況で、僕等が便利に使っていたのが QKC というソフトだった。この QKC は、JIS・EUC-jp・シフト JIS の3種類の文字コードの間での相互変換、そして LF・CR+LF・CR の3種類の改行コードの間での相互変換を簡単に行うことができる。しかも、ワイルドカードで複数のファイルを指定することができるので、とにかく便利だった。

今も僕は /usr/local/bin/ にこの QKC を入れているのだが、今回のような事態では、QKC だけでは用が足りない。というのも、QKC は UTF-8 を扱うことができないのである。この辺の話はこの blog でも『今更漢字コード』(on 2011/01/24)で触れているのだが、ここで言及している NKC という ruby スクリプトはもう入手できなくなっている。公開元サイトがドメインごと消失してしまったのだ。

ということで、とりあえず頭の体操である。先の LF とか CR とかいうのをエスケープシーケンスで書くと、前者が \n で後者は \r である。だから、文字コードが単一であるならば、この2者を置換してやればいいということになる。UNIX には tr という便利なコマンドがあるので、たとえば LF を CR に置換するならば、

$ tr \\n \\r < foo.txt > bar.txt
とかしてやればいい。CR+LF を LF にするのなら、-d オプションを使って、
$ tr -d \\r < foo.txt > bar.txt
で出来そうだ。逆だったら……まあ、僕はこういうときは sed を使うのだけど、
sed -e 's/$/\r/' foo.txt > bar.txt
……こんな感じか。

しかし、tr を使うにせよ、sed を使うにせよ、ワイルドカードで一発処理、というわけにはいかないので、スクリプトを書くことになる。それが面倒なことがあるので、僕はこの手の処理をするときには、改行コードの変換を QKC で行い、文字コードの変換を NKF で行うことが多い。たとえば、

nkf -w --in-place ./*.txt
のように --in-place オプションを使えば、NKF でもワイルドカードを使った一発処理が可能になる。実は今回は、Microsoft のシステム上で作られたと思しきファイルを、まず QKC で改行コードを変え、次に NKF で文字コードを UTF-8 に変えた。このご時世、こんなことでバタバタやっているのは僕位なのかもしれないけれど、メモ代わりに、そして時代の記録として、これを書いておくことにする。

Profile

T.T.Ueda
Tamotsu Thomas UEDA

茨城県水戸市生まれ。

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

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

New Entries

Comment

Categories

Archives(902)

Link

Search

Free

e-mail address:
e-mail address