2015年5月10日

nkfとiconvの差異

JIS系文字コードとUnicodeとの変換によく使われるnkfとiconvの変換にどれくらい違いがあるのか調べてみました。

EUC-JIS-2004とShift_JIS-2004のファイルをそれぞれUTF-8に変換して、その結果を比較します。

nkf Network Kanji Filter
http://sourceforge.jp/projects/nkf/

libiconv
http://www.gnu.org/software/libiconv/

変換元となるファイルについては、プロジェクトX0213の「JIS X 0213とUnicodeの対応表」から、文字付き版のファイルを使用しました。

JIS X 0213とUnicodeの対応表
http://x0213.org/codetable/

EUC-JIS-2004とUnicodeの対応表 文字付き版
http://x0213.org/codetable/euc-jis-2004-with-char.txt

Shift_JIS-2004とUnicodeの対応表  文字付き版
http://x0213.org/codetable/sjis-0213-2004-with-char.txt


今回使用した環境、バージョンは以下の通りです。

  • cygwin 2.0.2 (0.287/5/3)
  • gcc 4.9.2
  • nkf 2.1.3
  • libiconv 1.14

ちなみにJIS X 0213のサポートは、nkfでは2.1.3から、libiconvではおそらく1.8(?)からのようです。


    ビルド

    まず、それぞれをビルドします。

    nkf 2.1.3 をビルド。

    $ tar zxf nkf-2.1.3.tar.gz 
    $ cd nkf-2.1.3
    $ make

    libiconv 1.14 をビルド。EUC-JIS-2004とShift_JIS-2004を使えるようにするため、オプション --enable-extra-encodings を指定します。 

    $ tar zxf libiconv-1.14.tar.gz
    $ cd libiconv-1.14
    $ ./configure --enable-extra-encodings
    $ make

    EUC-JIS-2004

    次に、EUC-JIS-2004の変換をします。

    nkf
    JIS X 0201 片仮名を JIS X 0208 片仮名に変換しないように、オプション -x を指定します。

    $ nkf-2.1.3/nkf -x --ic=EUC-JIS-2004 --oc=UTF-8 euc-jis-2004-with-char.txt > euc-jis-2004-nkf.txt

    iconv
    $ libiconv-1.14/src/iconv_no_i18n -f EUC-JIS-2004 -t UTF-8  euc-jis-2004-with-char.txt > euc-jis-2004-iconv.txt

    それぞれの出力ファイルを比較します。

    $ diff  euc-jis-2004-nkf.txt euc-jis-2004-iconv.txt
    204c204
    < ‾     0xA1B1  U+203E  # OVERLINE      Windows: U+FFE3
    ---
    >  ̄    0xA1B1  U+203E  # OVERLINE      Windows: U+FFE3
    266c266
    < ¥     0xA1EF  U+00A5  # YEN SIGN      Windows: U+FFE5
    ---
    > ¥    0xA1EF  U+00A5  # YEN SIGN      Windows: U+FFE5

    EUC-JIS-2004の変換では、2つの文字で異なる変換結果が得られました。

    • オーバーライン (0xA1B1)
      • nkf   U+203E
      • iconv   U+FFE3
    • 円記号 (0xA1EF)
      • nkf   U+00A5
      • iconv   U+FFE5

    Shift_JIS-2004

    次に、Shift_JIS-2004の変換をします。

    nkf
    JIS X 0201 片仮名を JIS X 0208 片仮名に変換しないように、オプション -x を指定します。
    $ nkf-2.1.3/nkf -x --ic=Shift_JIS-2004 --oc=UTF-8 sjis-0213-2004-with-char.txt > sjis-0213-2004-nkf.txt

    iconv
    $ libiconv-1.14/src/iconv_no_i18n -f Shift_JIS-2004 -t UTF-8  sjis-0213-2004-with-char.txt > sjis-0213-2004-iconv.txt


    それぞれの出力ファイルを比較します。

    $ diff sjis-0213-2004-nkf.txt sjis-0213-2004-iconv.txt
    118c118
    < \     0x5C    U+00A5  # YEN SIGN
    ---
    > ¥     0x5C    U+00A5  # YEN SIGN
    152c152
    < ~     0x7E    U+203E  # OVERLINE
    ---
    > ‾     0x7E    U+203E  # OVERLINE
    298c298
    < ‾     0x8150  U+FFE3  # FULLWIDTH MACRON
    ---
    >  ̄    0x8150  U+FFE3  # FULLWIDTH MACRON
    360c360
    < ¥     0x818F  U+FFE5  # FULLWIDTH YEN SIGN
    ---
    > ¥    0x818F  U+FFE5  # FULLWIDTH YEN SIGN

    Shift_JIS-2004の変換では、4つの文字で異なる変換結果が得られました。

    • 円記号 (0x5C)
      • nkf   U+005C
      • iconv   U+00A5
    • オーバーライン (0x7E)
      • nkf   U+007E
      • iconv   U+203E
    • 全角マクロン (0x8150)
      • nkf   U+203E
      • iconv   U+FFE3
    • 全角円記号 (0x818F)
      • nkf   U+00A5
      • iconv   U+FFE5


    nkfでは、0x5Cと0x7Eは文字の意味に沿って変換するのではなく、ASCII互換として扱うようです。
    で、足りなくなった分を全角マクロンと全角円記号で補っている感じでしょうか。
    この辺りはオプションなどで色々変えられるのかもしれませんが、そこまでは調べませんでした。

    今回の使用・作成したファイルをGitHubに上げていますので、興味のある方はご覧ください。
    https://github.com/nathancorvussolis/difference-between-nkf-and-iconv

    2015年5月2日

    IMEの拡張機能


    IMEの各種設定のうちキーバインドやローマ字仮名変換ルールなどは基本的な機能として用意されていることがほとんどですが、例えば、標準以外の辞書を使いたいとか候補を整形したいなどの要望に答えるため、いくつかのIMEでは簡易的なスクリプトを組むことでそれらを実現できる機能を持っています。

    実現可能な機能については各IMEによって異なりますが、主に以下のような機能を有しているようです。
    1. 外部からデータを取得する
    2. 外部にデータを出力する
    3. 動的に候補や注釈を生成する
    4. これらをスクリプト言語で組める
    以下、拡張機能を持っているWindows用IMEの紹介です。


    ATOK


    ATOKダイレクトAPI
    http://atok.com/useful/developer/api/

    使用言語 : Perl, Ruby, Python


    SKK日本語入力FEP


    SKKGate
    http://coexe.web.fc2.com/skkgate.html
    SKKプラス
    http://coexe.web.fc2.com/skkextend.html

    使用言語 : JavaScript など


    CorvusSKK


    Lua拡張
    https://github.com/nathancorvussolis/corvusskk/wiki#Lua
    https://github.com/nathancorvussolis/corvusskk/blob/master/installer/config-lua/init.lua

    使用言語 : Lua


    SKK日本語入力FEPとCorvusSKKに関しては、操作体系の元ネタであるSKKがEmacsLispで記述された候補を実行して動的に候補を生成する機能を元々持っているので、これを拡張可能にしているのも自然な流れかなと思います。

    Windows用IMEでユーザー数が多いMS-IMEとGoogle日本語入力には拡張機能はないようですが、Android用のGoogle日本語入力やATOKには他のアプリのと連携を行うマッシュルーム機能があるそうです。

    以前某IMEでも話題になりましたが、気を付けなければならないのがIMEのセキュリティについてです。
    拡張機能を不用意に使うと穴ができる可能性があるので、製作者側にも使用者側にも慎重さが求められます。

    IME as a Possible Keylogger (symantec)
    https://www.symantec.com/avcenter/reference/ime.as.a.possible.keylogger.pdf

    それでは、良い連休を。

    2015年3月11日

    SKK-JISYO.stationを更新した話 (2)

    前回は本題からちょっと脇道に逸れてしまったので、今回は更新作業そのものについて書きたいと思います。
    まあ、あまり大した話ではないですが。

    資料探し


    まず、手元に情報がないため資料を探すことから始めます。
    SKK-JISYO.stationは廃線、廃駅については削除をしない方針で、最後の更新が2005年なので、
    1. 期間は2006年〜2014年の範囲 (一応2005年もチェックしておく)
    2. 駅、路線、鉄道会社で新規もしくは名称が変更されたもの
    という条件で探します。良さげな以下の2つを見付けたのでこれらを元ネタとすることにします。

    更新用辞書作成


    あとはひたすら単純作業です。
    1. Category:開業年別鉄道駅に記載されている駅をWikipediaで検索し、日付の項目をチェック
    2. 更新用の辞書ファイルにエントリを追加
    3. 1〜2を繰り返す
    さらに、駅データベースで改称とされている駅についても同様にエントリを追加していきます。
    Wikipediaのほうは中国、台湾、韓国の駅も多数含まれていて紛らわしいので逆にしておけば良かったと、このあたりで少し後悔。

    同音異字のチェック


    次に、更新用の辞書ファイルのなかで同音で異なる字の駅がSKK-JISYO.stationにないかどうかをチェックします。

    今回は「なかのしまえき /中之島駅/」と「ぞうしがやえき /雑司が谷駅/」が該当したので、注釈を付けて「なかのしまえき /中之島駅;中之島線/」、「ぞうしがやえき /雑司が谷駅;副都心線/」とします。
    さらに「ぞうしがやえき」には元々1つしか候補がなかったので既存の候補に注釈を付加した「ぞうしがやえき /雑司ヶ谷駅;荒川線/」も追加します。
    ちなみに、「なかのしまえき」のエントリには南武線「中野島駅」、札幌市営地下鉄南北線「中の島駅」が既に登録されていました。

    「〜えき」「〜駅」無しの更新用辞書作成


    SKK-JISYO.stationには見出し語の「〜えき」と候補の「〜駅」が無いエントリも登録されているので、更新用の辞書ファイルをベースとして「えき」および「駅」を取り除いたバージョンの更新用辞書を作成します。

    マージ


    既存のSKK-JISYO.stationと更新用の2つの辞書ファイルを拙作のmeskkdicを使ってマージし、ファイル先頭のコメント行を追加します。
    Unix系であれば、skkdic-exprskkdic-sort、またはskkdic-expr2を使うと良いと思います。
    念のため、既存の辞書と新しい辞書のdiffをとって問題がないかどうか確認します。

    コミット


    そして最後に、openlab.jpのCVSにコミットして完了です。



    と、ここまで書いて、大阪市営地下鉄今里筋線、東京メトロ副都心線などの路線名が漏れていたことに気が付きました。
    あとで追加しておきます。

    2015年3月9日

    SKK-JISYO.stationを更新した話

    2015年2月末、TwitterでSKK関連のつぶやきを眺めていたところSKK-JISYO.stationに吉川美南駅(武蔵野線 吉川駅と新三郷駅の間)が載っていないとの発言を見かけました。SKK-JISYO.stationを調べてみたら2005年を最後に実質的な更新がされておらずコメント部分のみの更新に留まっていました。

    これはいかん、ということで翌3月になって時間ができたときに作業開始。2006年〜2014年だとしても丸9年もありますが、幸いにもSKK-JISYO.stationは廃線、廃駅は残したままとしておく方針なので、新規と変更だけに絞ることとし、更新用の辞書を作って最終的に既存の辞書とマージしてコミットしました。しかし、翌日見直したら1件だけ漏れが見付かったのでこれを追加して再度コミットし、特に問題なく作業完了しました。

    気になった点としては、名称が「〜停留場」や「〜停留所」などであっても「〜駅」となっているところでした。(例:都電荒川線 三ノ輪橋停留場) この使い分けについては、法律や省令で決められていたり設備の違いだったり昔の名残もあったりして素人が判別するのはなかなか難しいようです。基本的には鉄道会社が呼んでいる名称が良さそうなのですが、今回は以前からの方針に沿って「〜駅」で統一しました。

    また、廃線が思っていたより多いという印象を受けました。

    以下、今回更新した範囲で個人的に気になった出来事を挙げてみました。(注:かなり関東に偏っています。)
    • 2008年3月30日 日暮里・舎人ライナー開業
    • 2008年3月30日  横浜市営地下鉄グリーンライン開業
    • 2010年10月21日 東京国際空港国際線ターミナル開業
      • 京急空港線 「羽田空港国際線ターミナル駅」開業
      • 京急空港線 「羽田空港駅」が「羽田空港国内線ターミナル駅」に改称
      • 東京モノレール羽田空港線 「羽田空港国際線ビル駅」開業
    • 2012年3月17日 東武伊勢崎線 「業平橋駅」が 「とうきょうスカイツリー駅」に改称
    • 2012年8月20日 東日本大震災で不通になっていた気仙沼線のうち、柳津駅〜気仙沼駅の区間でBRTの暫定運行開始

    そして今年2015年は、3月14日に予定されている北陸新幹線の長野駅〜金沢駅の開業と、上野東京ラインの開業がありますね。ちなみに、長野新幹線は正式には北陸新幹線という名称で、東京駅〜長野駅の区間が便宜的にそう呼ばれていただけのようで、今後は「北陸新幹線(長野経由)」など表記するそうです。

    なるべく漏れが無いように調べたつもりですが、私自身鉄道にあまり詳しくないこともあり調べきれていない可能性があります。 もし2014年までに開業、改名した駅、路線、鉄道会社で記載されていないものがありましたらTwitterなどで私まで知らせていただければ対応しますので、よろしくお願いします。

    今回更新したSKK-JISYO.stationは、こちらからダウンロードできます。


    そういえば、コンピューター関係の記事を巡回しているとやけに詳しい電車の記事が面白かったなあ、と思い出したのでリンクを貼っておきます。


    確か最初に読んだのが、向谷実さんが京阪電鉄の発車メロディを作った話でした。読み物として、あまり電車に詳しくなくても(詳しかったら多分もっと)面白いかと思います。

    2015年1月11日

    SKKの個人辞書

    あけましておめでとうございます。

    SKK風の入力方式には様々な実装があり、それぞれの実装毎で個人辞書が管理されています。
    色んな環境を使用する人にとって、どの実装でも共通の個人辞書を使えないか、という考えが浮ぶのは自然なことかと思います。

    そこで、SKK辞書サーバーを拡張して辞書検索のみならず辞書登録も可能なサーバーがあればいいのでは、という発想もまた自然なことだと思います。そのような機能を持ったサーバーで現在公開されているものは存在しないようですが、GoogleDriveやDropboxのAPIを使ったりできたら非常に面白いかな、と個人的には思ったりしています。

    さて、SKKの個人辞書はEUC-JPやUTF-8などのプレーンテキストなので、ユーザーにとって適当なタイミングで取り込んだりしたほうが柔軟性があって良いのもまたしかりです。

    以前 .skk-jisyo を自動的に取り込めないかという要望が寄せられたことがありました。 そこで回答したcveuc.exemeskkdicw.exeを使って.skk-jisyoをCorvusSKKの個人辞書に取り込むバッチファイルを一部改変したものを以下に記述します。

    ----- ここから -----

    pushd %~dp0

    @rem サーバープロセスを終了
    taskkill /im imcrvmgr.exe


    @rem .skk-jisyoをUTF-16(LE)に変換 (.skk-jisyoがEUC-JIS-2004かEUC-JPの場合)
    cveuc.exe -e -W "%USERPROFILE%\.skk-jisyo" skk-jisyo-utf16.txt

    @rem .skk-jisyoをUTF-16(LE)に変換 (.skk-jisyoがUTF-8の場合)
    @rem cveuc.exe -u -W "%USERPROFILE%\.skk-jisyo" skk-jisyo-utf16.txt


    @rem ユーザー辞書とマージ (.skk-jisyoを優先する場合)
    meskkdicw.exe skk-jisyo-utf16.txt + "%AppData%\CorvusSKK\userdict.txt" skk-jisyo-utf16-new.txt
    meskkdicw.exe -O skk-jisyo-utf16.txt + "%AppData%\CorvusSKK\userdict.txt" skk-jisyo-utf16-new.txt

    @rem ユーザー辞書とマージ (CorvusSKKのuserdict.txtを優先する場合)
    @rem meskkdicw.exe "%AppData%\CorvusSKK\userdict.txt" + skk-jisyo-utf16.txt skk-jisyo-utf16-new.txt
    @rem meskkdicw.exe -O "%AppData%\CorvusSKK\userdict.txt" + skk-jisyo-utf16.txt skk-jisyo-utf16-new.txt


    @rem マージしたユーザー辞書をコピー
    copy /y skk-jisyo-utf16-new.txt "%AppData%\CorvusSKK\userdict.txt"

    @rem 一時ファイルを削除
    del skk-jisyo-utf16.txt
    del skk-jisyo-utf16-new.txt

    @rem サーバープロセスを起動
    start "" "%SystemRoot%\System32\IME\IMCRVSKK\imcrvmgr.exe"

    popd

    ----- ここまで -----


    昨年はSKK-JISYO.lispをコミットさせてもらったりしたので、今年はddskk本体でも何か貢献できればと思っています。ddskk本体の開発環境がSKK OpenLabのCVSからGitHubに移行し、EmacsのパッケージシステムであるMELPAに登録されたりと、オラなんだかわくわくしてきたぞ状態の今日この頃です。