Ruby 1.9 における日本語処理のポイントをまとめてみました

私はとっても文系なので日本語処理をしたくてしたくて仕方ないのは当然のことです。しかし日本語の処理ということを考えますと、文系の一般的な感覚としましてはこれまでやはり実績とノウハウの蓄積から、Perlが用いられることが多かったのではないでしょうか(いや、でも今となっては、もうそうでもない?私の頭が古いだけ?)。実際のところ私もPerlを使ってきたわけなのですが、最近めっきりPerlを実用しなくなってしまいましたので、日本語の処理もやはり手慣れたRubyでやっつけたくなるわけです。これまでもRubyで日本語処理はしてきたわけですが、1.9ならこれまで以上にとっても簡単だよ!ということを先日以下の記事を書いていて感じましたので、これを簡単にまとめておきたいと思います。

ところで、Perlは私にプログラミングに必要なほとんどの知識を授けてくれた、とても恩義ある言語です。オブジェクト指向を学んだのもRubyからではなくPerlからでした。日本語処理をしたいだけなら、現在のところPerlの方がはるかに便利だと思います。この観点において敢えてRubyを使うメリットは正直ないと思いますが、でもRubyが好きな人は参考にしてみて下さい。

てな前置きなので、文系の人にとっても優しく書いていきたいと思います。だからここで説明するのは、基本的な操作だけどこれが分からないとどうにも始まらないだろう次の三つだけです。

  • ファイルを読み込む
  • 一文字ずつ処理する
  • 日本語に対する正規表現

ファイルを読み込む

何かテキストなどを読み込んでそれを対象として処理したいと考えた場合、文字のエンコーディングについて注意しておく必要があります。色々種類があって良く分からないよね、面倒だよね、と思うわけですが、まぁ大体のところSJISEUCUTF-8のいずれかを扱う場合がほとんどではないでしょうか。なお、スクリプト自体はUTF-8で書くことを想定しています、最初のマジックコメント"# -*- encoding: UTF-8 -*-"はとっても重要だから忘れないでね!

# -*- encoding: UTF-8 -*-

# 一行づつ読み込んで何か処理したい場合は次のような感じになります

# UTF-8 ならそのまま
File.open("foo.txt").read_line do |line|
  # 行に対する処理
end

# スクリプトはUTF-8でエンコードされていますので、
# SJIS なファイルを読み込む場合にはオプションを付けます
File.open("foo-sjis.txt", "r:SJIS").read_line do |line|
  # 行に対する処理
end

# 同様に EUC-JP の時にもオプションを付けておきます
File.open("foo-euc.txt", "r:EUC-JP").read_line do |line|
  # 行に対する処理
end

一文字ずつ処理する

1.8では$KCODEを設定して云々してきたわけですが、1.9からはマジックコメントもしくは -E オプションを指定することで一文字づつの処理がとっても安心確実になっております。

"あいうえお".each_char do |char|
  # 文字に対する処理
end

ついでに文字の配列が欲しい場合には次のようにします。

"あいうえお".chars.to_a # => ["あ", "い", "う", "え", "お"]

日本語に対する正規表現

文字クラスがとっても便利です。でも文字Propertyを使う時には正規表現リテラルのしっぽに"u"を忘れないでね!忘れるとエラーになりますよ(正確に言うと/\p{Katakana}/だと u が必須で /あ\p{Katakana}/ なら u を付けなくても大丈夫。ちょっと混乱しそうだから、いっつも u をつけておけば解決?)。

# -*- encoding: UTF-8 -*-

# ひらがなだけを出力したい時には /\p{Hiragana}/u が大活躍

"あいうえお一二三々".each_char do |char|
  print char if /\p{Hiragana}/u =~ char
end
# => あいうえお

# 漢字等(ただし踊り字などを含みます)だけを出力したい時には /\p{han}/u
"あいうえお一二三々".each_char do |char|
  print char if /\p{Han}/u =~ char
end
# => 一二三々

# 例えば踊り字などを除いて純粋に漢字
# (ただしCJK統一漢字の範囲)だけ出力したい時には
"あいうえお一二三々".each_char do |char|
  print char if /[\u4E00-\u9FFF]/u =~ char
end
# => 一二三

てな感じです。1.9からは正規表現エンジンがonigurumaに変わり、とっても便利になっています。このおかげでこれまで漢字等やひらがな、かたかなだけを抽出したい時の慣用句 /[亜-腕]/ とか /[あ-ん]/ とかのアレが必要ないんですよ!(でもホントは /[亜-腕]/ は必要だよ!)

http://www.geocities.jp/kosako3/oniguruma/doc/RE.ja.txt

あと、ユニコード文字の \u 表現がとっても便利に使えます。これを利用するとユニコードブロックの範囲指定が簡単ですのでとっても使い勝手がいいと思います。各ブロックの範囲については例えば以下を参照して下さい。

Unicode - Wikipedia

具体的には、例えば「CJK互換用文字」だけを抽出したい、という場合には、そのコードブロック「U+3200-32FF」に注目して、/[\u3200-\u32FF]/ みたいに書くといいと思います。

まとめ

でも、そもそもRuby1.9の導入方法とかどうすんの?とか言われても、どうしようもないですよね。それに1.9はとても流動的だから、常日頃変更点に追随していってね!とはさすがに言えないし。やっぱりPerl使った方が無難で楽じゃないかなと思いました。Perl の ShiftJIS::Regexp とか見たら充実しまくってて便利そうですごいなぁと圧倒されました。