日本語(カタカナ)を音節単位で分かち書き【Python】


はじめに

日本語(カタカナ文字列)を音節単位で分かち書き(音節分かち書き)するpythonの関数を作りました。

元文 モーラ分かち書き 音節分かち書き
ガッキューシンブン ガ/ッ/キュ/ー/シ/ン/ブ/ン ガッ/キュー/シン/ブン
アウトバーン ア/ウ/ト/バ/ー/ン ア/ウ/ト/バーン

日本語の音韻の代表的な分割単位としてモーラと音節があります。モーラはいわゆる俳句の「5・7・5」を数えるときの区切り方で、長音(ー)、促音(ッ)、撥音(ン)も1拍と数えます。それに対し、音節では長音、促音、撥音は単体で数えられず、直前の単一で音節となれるカナと合わせてひとつの拍と見なされます。「バーン」のように長音、促音、撥音が連続した場合は3以上のモーラ数で1音節となります。詳細はモーラ - Wikipediaを御覧ください。

本稿では音節単位での分かち書きについて説明します。
モーラ単位での分割については下記で説明しています。
日本語(カタカナ)をモーラ単位で分かち書き【Python】

環境

  • macOS Catalina 10.15.4
  • python3.8.0

方針

考えやすくするために、入力は記号を含まない全角カタカナの文字列とします。また、長音で表せるところは長音に変換されているものとします。これは例えば「ガッキュウ」は「ガッキュー」のように表現されているという意味です。
なお、漢字仮名交じり文を発音のカタカナ文字列に変換する方法は別記事にまとめましたので、もしよければ御覧ください。ただし、MeCabを使っていますので、辞書にない言葉は変換できません。

このとき、音節の構成条件を下記のように定義します。

【下記1-4と「ー/ッ/ン」の連続(0文字含む)文字列】
1. ウ段+「ァ/ィ/ェ/ォ」
2. イ段(「イ」を除く)+「ャ/ュ/ェ/ョ」
3. 「テ/デ」+「ィ/ュ」
4. 上記以外の大文字カナ1文字

これは

正規表現 意味
[ウクスツヌフムユルグズヅブプヴ][ァィェォ] ウ段+「ァ/ィ/ェ/ォ」
[イキシシニヒミリギジヂビピ][ャュェョ] イ段(「イ」を除く)+「ャ/ュ/ェ/ョ」
[テデ][ィュ] 「テ/デ」+「ィ/ュ」
[アイウエオカ-ヂツ-モヤユヨ-ヲヴ] ①②③以外の大文字カナ1文字
[ーッン]* 「ー/ッ/ン」の連続文字列(0文字含む)

としたとき、'(①|②|③|④)⑤'のように書けます。

コード

import re

#「((ウ段+「ァ/ィ/ェ/ォ」)|(イ段(「イ」を除く)+「ャ/ュ/ェ/ョ」)|( 「テ/デ」+「ィ/ュ」)|(大文字カナ))(「ー/ッ/ン」の連続文字列(0文字含む))」の正規表現
c1 = '[ウクスツヌフムユルグズヅブプヴ][ァィェォ]' #ウ段+「ァ/ィ/ェ/ォ」
c2 = '[イキシシニヒミリギジヂビピ][ャュェョ]' #イ段(「イ」を除く)+「ャ/ュ/ェ/ョ」
c3 = '[テデ][ィュ]' #「テ/デ」+「ィ/ュ」
c4 = '[アイウエオカ-ヂツ-モヤユヨ-ヲヴ]' #大文字カナ
c5 = '[ーッン]*' #「ー/ッ/ン」の連続文字列(0文字含む)

cond = '(?:'+c1+'|'+c2+'|'+c3+'|'+c4+')'+c5 #(?:)はサブパターンの参照を避けるカッコ
cond = '('+cond+')'
re_syllable = re.compile(cond)

def syllableWakachi(kana_text):
    return re_syllable.findall(kana_text)

text = 'シンシュンシャンソンショー'
print(text)
print(syllableWakachi(text))
print('')

text = 'トーキョートッキョキョカキョク'
print(text)
print(syllableWakachi(text))
print('')

text = 'アウトバーン'
print(text)
print(syllableWakachi(text))
print('')

text = 'ガッキュウホウカイ'
print(text)
print(syllableWakachi(text))

出力は下記です。

シンシュンシャンソンショー
['シン', 'シュン', 'シャン', 'ソン', 'ショー']

トーキョートッキョキョカキョク
['トー', 'キョー', 'トッ', 'キョ', 'キョ', 'カ', 'キョ', 'ク']

アウトバーン
['ア', 'ウ', 'ト', 'バーン']

ガッキュウホウカイ
['ガッ', 'キュ', 'ウ', 'ホ', 'ウ', 'カ', 'イ']