2009-02-19

漢字かな交じりの文字列と、その読みが与えられたときに、漢字とその部分の読みがなとをプログラム上で対応させる方法の私的メモ。限定的すぎる話でごめん。

「漢字かな交じり」という文字列に対して「かんじかなまじり」という読みがなが与えられたとする。これを、

漢字
かんじ

のように、対応づけたい。楽をするために正規表現を使います。

import re

word = u'漢字かな交じり'
reading = u'かんじかなまじり'

まず、かな文字のテーブルを用意する。

kana_letters = u'あいうえおかきくけこ...'

続いて、以下のような正規表現を構築する。

rx_word = re.compile('([^%s]+|.)' % kana_letters)

これは、「かな文字以外の任意の文字の連続、またはかな1文字」を表している。この正規表現にマッチする単位で文字列を区切っていく。

L = rx_word.findall(word)

ここで L[u'漢字', u'か', u'な', u'交', u'じ', u'り'] になっている。この単位で、今度は読みがなにマッチさせる正規表現を作る。

tokens = []
for term in L:
    if term in kana_letters:
        tokens.append('(%s)' % term)
    else:
        tokens.append('(.+)')
re_reading = '^%s$' % ''.join(tokens)
rx_reading = re.compile(re_reading)

分割された文字列がかな文字であればそれをそのまま、かなでなければ '.+' のパターンを割り当てて、それを連結する。re_readingu'^(.+)(か)(な)(.+)(じ)(り)$' になっている。あとはお察しの通りこれを読みがな文字列である reading にマッチさせる。

m = rx_reading.match(reading)
if m:
    for term, term_reading in zip(L, m.groups()):
        print term, '-', term_reading

re_reading の各パターンを括弧でくくっておいたので、m.groups() でマッチ部分をリストとして取り出せる。この数は L に一致してるはずなので、zip 関数で双方をセットにしてひとつずつ取り出せる。

結果。

漢字 - かんじ
か - か
な - な
交 - ま
じ - じ
り - り

基本は以上。表記揺れとかカタカナ対応とか各漢字ごとの読みの推測などをやろうとすると他にも工夫が要るけど、骨子は同じ。