当ウェブサイトは安全と利便性向上のためにクッキー(Cookies)を使用しています。詳細はこちら

法人向けクラウド・ネットワークサービスのPacketFabric

青空文庫の第三第四標準文字を変換する

2015年04月30日

青空文庫のshift-jisテキストをutf-8に変換するだけなら、iconv -f sjis -t utf8 .. とか打ってしまえば済みますが、けど待ってください。青空文庫のsjisはJISX0208です。UTF8ならJIS0213も表現できるのにですよ。これはどないかできないか、と考えてしまいますね。大多数を置いてけぼりにしている感もありますが、「青空文庫のテキストをUTF8化してJIS0213でちゃんと表現してみよう」というお話です。動作は全てLinux上で検証していますので、linuxのマシン上でお試しください。


エンコーディングというか、文字コードのお話

実際は文字コードについてとても詳しい諸先輩方がいらっしゃいますのでそちらをご参照いただくとして、実用的な人間としては以下を知っておけばよいのではないか、と自分では思っています。もっと勉強しなくちゃという反省はあります。

  • ASCII
    英語の文字を表す文字表(文字コードと言います)。コンピュータの世界ではいつの間にか世界標準に。1つの文字を7bit、1byte未満で表現しています。つまり制御文字含めて128文字。
  • Shift-JIS
    後述するJISコードをシフトして(ずらして)、日本語1文字を2byteで表現できるようにしています。Windowsで使われています(したでしたっけ?)
  • EUC-JP
    これもまた後述するJISコードから、日本語1文字を2byteで表現できるようにしています。Macとか古いLinuxのdistroではこれが標準。
  • ISO-2022-JP
    なんだっけこれ。メールとかで使う、7bitの数字の組み合わせで文字を表現するコードのはず。あまり使わないので正直知らなくても何とかなるかな、と。
  • utf-8
    日本語を2byteから3byteで表現するようにしてます。ASCIIコードのすごい拡張版、みたいなものです。最大4byteで文字を表します。

インターネットを使っていると、たまに文字化けというか、日本語が化けて表示されることがありますが、これはブラウザが推測した文字コードと実際の文字コードが異なるために正しい文字が表示できないのです。最近は文字コードをはっきり指定することが殆どで、自動判別で大体正しく表示されるんですが、たまに自動判別に失敗する場合もあるので、正しく日本語を表示するためにShift-JIS, Euc-JP, UTF-8など幾つかの単語を覚えておくと便利です。


JIS漢字コードが大元

とりあえず、文字コードというものがあることはインターネットブラウザの設定などを見て気づいている方もいるかと思うのですが、その大元をたどれば JIS(日本工業規格)の漢字表、漢字コードになるわけです。この漢字表にはいくつかバージョンがあり、バージョンをつけてJIS0208とか JIS0213と言われています。概要としてはこれくらい知っていれば良いと思います。

Shift-JISもEUC-JPも、JIS漢字コードを基にして作られているため、JIS漢字コードが新しくなった時にそれにあわせて拡張をしなければなりませんし、古い規格の古い文字コードを前提とするテキストについては、対応してない文字は正しく表示されません。青空文庫ではこのような機種依存で正しく表示されない可能性を防ぐため、一定のルールを定めています。意図的にJIS第三水準や第四水準の文字を表示しないのです。後方互換ですね。


まずは変換表を作る

いろいろな話を考えないで、ただ文章を読むだけなら実はxhtml版を読むのが一番簡単ですし、青空文庫に関わる方の努力に感謝しつつ読めばいいんですけど、せっかくテキストファイルがあるのなら、それをちゃんとテキストで表示したい、変換したいのがエンジニアの性。とりあえずスクリプトで変換してみようじゃないですか。

まずは変換テーブルを作ります。青空文庫テキストでは、第三水準の漢字は次のように表現されます。

※[#「埒のつくり+虎」、第3水準1-91-48]
(「山月記」中島敦、青空文庫のテキストファイルから抽出しました。図書カードはこちら)

大事なところは後半、「第3水準1-91-48」と書かれているところです。これが実際のJISのコード、面区点番号です。

WikipediaのJIS X 0213漢字一覧の1面という記事には、以下の記述があります。

虢 1-91-48 0xEE6F U+8662 第3水準

ちなみにWikipediaもutf-8で記述されていますし、フォントさえインストールされていれば「虢」が表示されるはずです。


フォントのインストール

そうそう、第三や第四水準など新しいJISにあわせて文字コードも拡張されていきます。今までは存在しなかった文字も、新しい文字コー ドに対応した フォントでは存在しているかもしれません。IPAフォントなどフリーで公開されているフォントもあります。まず新しいフォントを利用してみましょう。


第三、第四標準を見つける

WikipediaのJIS X 0213漢字一覧の1面とJIS X 0213漢字一覧の2面の記事を利用して、 虢 1-91-48 0xEE6F U+8662 第3水準 という「文字,JISコード,SJISコード,Unicode」ていう変換テーブルを作成することが可能ですね。わかりづらいので

1-91-48 虢

このような、「JIS漢字コード(面区点番号), 文字」というリストにしてしまいます。Wikipediaのページをテキストで保存し、例えば menkuten.txtとした場合、以下の1行コマンドで簡単にできます。

cat menkuten.txt | while read kanji jis sjis unicode suijun memo ; do echo $jis $kanji ; done


sed grep, またsed

ここまできたら後は簡単です。簡単かな。PerlやPython使えばもっと簡単だと思いますが、とりあえずLinux使いであれば殆どの人が使うbash上でやってみます。やることは

※[#「埒のつくり+虎」、第3水準1-91-48]

を見つけて、 [# から ] までの文字列を拾い、中にある「1-91-48」の数字が示す漢字に変換する、ですね。こういう時はsedですが、第三、第四標準の全文字分ループでsedをかけるとなると時間がかかるので(10000文字くらいあるので)、それは避けたいと思います(最初それでやろうとしたのですが時間かかるのでやめました)。元のファイルはtext.txtというutf-8のテキストファイルに変換しています。

  1. テキスト中に出てくる第三、第四標準を見つけて、該当の漢字コードのみを抜き出した変換テーブルを作る
    テーブル1行ごとからsedのスクリプトを作って実行という流れを作ります。 テンポラリで以下のファイルを作ります(本当はtempfileなどで安全なファイルを作った方がいいですよね)

    grep -Eo “※[#「.{1,15}」、第[1-4]水準[0-9]{1,2}-[0-9]{1,2}-[0-9]{1,2}]” ./text.txt >> ./text.txt.grep

  2. 作ったファイルをソートしてuniqで重複を排除します。

    cat ./text.txt.grep | sort | uniq

  3. 抽出した行がテキストに含まれる第三、第四標準漢字の面区点番号になるので、Wikipediaから抽出した面区点と漢字の対応表から、テキストに含まれる分だけを抽出します。

    for $(cat ./text.txt.grep | sort | uniq | grep -o “[1-2]-[0-9]{1,2}-[0-9]{1,2}” ) ; do grep $i menkuten.txt >> ./text.txt.menkuten

    (本当は1-1-1 と 1-01-01の差異を吸収するために sed -E “s/-\([0-9]\)-/-0\1-/g”とかを間に入れます)

  4. ボトムアップでつくっているのでなんだか面倒なことしているかもしれませんが、抽出した第三、第四標準漢字の面区点番号を漢字に変換していきます。

    cat ./text.txt.menkuten | while read jis kanji | do sed ; done >> text.txt.convert


出来上がり

項目ごとに動く部品をつくって結合しているので、大量のテンポラリファイルを作ったり、似たような事をしてたりします。結合できる部分は結合したり、不要な部分は除いたりする最適化作業がありますが、まずは 正しく動作するために部品に分割して確認しながら完成させました。


で、結局これはなんなのか

今回は趣味で青空文庫のテキストを例として利用させていただきましたが、このような練習を随時行いながら、いざという時にログファイルや、ツールの出力結果などを手軽に解析するために、bashでできる事を増やしていく、bashに慣れていくといいかと思います。(czhなど別のshellの勉強などの場合でもいいんじゃないかなと思います)

もちろんpythonやperl, rubyなどを使ってより複雑なツール解析を行うようになれれば一番いいと思いますが、まずはbashなど標準コマンドですぐ出来る部分はあるということで。

grep や sed, sort, uniq, cut, tr, cat, while, read などのコマンドを使いこなし、自分の調べたいように調べたり、今回はbashですが、自分の環境にどういうツールがあるか、ツールをどう使えるかを知ることが、現場での想像力の発揮に繋がると思います。

各種お問合せ、お見積もり、資料請求に関するご質問を承っております。まずはお気軽にご連絡ください。

ページトップ戻る