文字コードの謎

HTML中に、「自」という数値文字参照があるとしよう。これがなぜかUnicodeの「0xE8 0x87 0xAA」の3バイトになってしまう、という話。(ちなみに「自」という字です)

この変換をしてしまうのは、

perl -X -pe ‘s/&#([0-9]*);/sprintf(“%c”, $1);/ge;’
という、数値文字参照を解決しようとした1-lineのフィルタだ。

10進数の33258は、16進数にすると、当然0x81eaである。これは「0xE887AA」とは似ても似つかない。そして、「自」の文字はEUC:0xBCAB、JIS:0x3C2B、SJIS:0x8EA9であって、同じ2バイトの0x81EAにはつながらないのだ。ちなみに0x81EAをUnicodeとして認識しようとしてもダメなのである。

こんな変てこりんなことになったのはこの人(mac.com)のせいである。この人のページはHTMLもRSSも、タグ以外の日本語文字が全部数値文字参照になっているという強烈な特性を持っているのである。中身は悪くないのだが…。たぶん、英語のソフトを無理矢理日本語で使っているのだろうな。

実は、情けないことにまだ解決してない。謎は続く。

(追記) 2003-09-11 17:50

実はPythonやPHPやawkで同じような書き方をしても「自(自)」を「自(0xE887AA)」に変換することはできない。Perlが偉いのだが、ただなぜ正しく動作してしまうのかが謎なのだ。

(追記) 2003-09-11 21:40

iconvで調べたところ、0x81eaが「自」である文字コードは、WCHAR_T、UCS-2BE(Big Endian?)、UCS-4など、Unicode系である。Perlは内部でUCS-2で管理しているために%cの引数がUCS-2になっていて、出力のときにUTF-8に変換しているのだろうか??

(追記) 2003-09-12 11:53

Cのprintfの場合、l修飾子をつけると(%lcとか%lsとか)ワイドキャラクタ系の引数として扱われる。perlは%cが%lcなんだろうな、たぶん。とりあえずこれで納得したことにする。

(追記) 2003-09-17 10:33

Pythonではフォーマット文字列をUnicodeにしとくといいみたい。

unicode(&#8220;%c&#8221;) %(33258) => u&#8217;\u81ea&#8217;<br /> (unicode(&#8220;%c&#8221;) %(33258)).encode(&#8220;japanese.euc_jp&#8221;) => &#8216;自&#8217;<br />

コメントはありません

  1. こんにちは、リファラーをたどってきました。

    小生のページのことがありますが、iBlog をつかっている関係で
    日本語表示は実態参照となります。

    ちゃんと表示されているので、またRSSも NteNewsWire などでは
    ちゃんと日本語でフィードされるので、特に不都合はないと思ってるのですが、
    なにか問題があるのでしょうか。

    検索エンジンにかかりにくいということはありますが、時間がたてば実体参照でも
    索引を作ってくれるようです。

  2. こんにちは。
    これは、XMLとしては問題なくて、仕様通りにちゃんと作ってあれば正しく処理できるのですが、(私のように)なんとなくパターンマッチだけでやっていると処理しにくいだけ、ということのようです。

    ただ個人的には、HTMLやXMLといったデータフォーマットは可読性を重視して作られていると思うので、使っている文字コードで表現できる部分には実体参照を使わないほうが合っていると思います。—–

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です