ヘボン式ローマ字を音素(母音、子音)に分解

# TL;DR

```bash:roman2phoneme_withN.sh
#!/bin/bash

# 撥音「ん」を"N"に置き換え前後にスペースを入れる
# NOTE: 母音のスペース区切りより先に変換しないとマ行が誤って「N+母音」になってしまう
sed -r "s/([nm])([^yaiueo])/ N \2 /g" |
# 母音の前後にスペースを入れる
sed -r "s/([aiueo])/ \1 /g" |
# 促音「っ」を"Q"に置き換え前後にスペースを入れる(チャ行以外)
sed -r "s/([^ \f\n\r\taiueo])(\1)/ Q \2/g" |
# 促音「っ」を"Q"に置き換えの前後にスペースを入れる(チャ行)
sed -r "s/tch/Q ch/" |
# 空白が連続する場合一つだけにする(見た目をきれいに)
sed -r "s/[ \f\n\r\t]+/ /g"
```

# やりたいこと
単語を音素ごとに区切りたい
（音声分析で、テキスト側の処理として何かと欲しくなるんです…）

# 困ったこと
「漢字→かな」や「かな→ローマ字」の変換ツールはたくさんありますが、
意外と「ローマ字→音素」に変換するツールがなかなか見つかりません…

というわけで「ローマ字→音素」変換を正規表現で作ってみましょう！

(ちなみに、漢字、かな→ローマ字変換は
[Variable name creation \| 漢字をローマ字・英語に変換します。変数名を作成するためのツールです。](http://hensumei.com/kanji-romaji)
や
[GitHub - miurahr/pykakasi: NLP: Convert Japanese Kana-kanji sentences into Kana-Roman in simple algorithm.](https://github.com/miurahr/pykakasi)
がおススメです。
この記事のローマ字サンプル作成でもお世話になりました。)


# ヘボン式のルール
こちらのサイトを参考にしました。
[ヘボン式ローマ字綴方表｜東京都生活文化局](http://www.seikatubunka.metro.tokyo.jp/passport/documents/0000000485.html)

訓令式より発音に忠実なヘボン式、「sh」「ch」とかの2文字子音だけじゃなく、「ん」や「っ」にもややこしいルールがあったのね…

# ソースコード
Linux版はbash, Windows版はPowershellなので、言語、ツール等のインストールは不要です。~~使うハードルを下げて、研究室で流行らせよう！~~

[GitHub - Syuparn/roman2phonemes: ローマ字文字列を音素(子音、母音)ごとにスペース区切り](https://github.com/Syuparn/roman2phonemes)

# 使い方
ヘボン式ローマ字を母音、子音ごとにスペースで区切ります。

```:input.txt
konnichiwa sekai
```

```:output.txt
k o n n i ch i w a s e k a i 
```
## 実行方法
### Linux
中身はただのsedなので、ターミナルで一行打ち込むだけです。

```bash
$ cat input.txt | bash ./roman2phoneme.sh > output.txt
```

### Windows
中身はただのPowerShellの `-replace` コマンドなので、PowerShellでコマンドを打ち込むだけで…

```
 > .\roman2phoneme.ps1 i.txt i2.txt                                 
.\roman2phoneme.ps1 : このシステムではスクリプトの実行が無効になっているため、
ファイル roman2phoneme.ps1 を読み込むことができません。詳細については、
...
```

……。（絶望）

PowerShellはセキュリティのため、デフォルトではスクリプト(ps1)ファイルの実行を禁止しています。
設定を緩めることもできるのですが、戻すのも手間なので、コマンドプロンプトから以下のように実行してください。

```
powershell -NoProfile -ExecutionPolicy Unrestricted -File ./roman2phoneme.ps1 input.txt output.txt
```

これで、一時的にPowerShellのスクリプト実行が許可されます。

(参考: [Powershellを楽に実行してもらうには - Qiita](https://qiita.com/tomoko523/items/df8e384d32a377381ef9))

### Mac
手元に無いので未確認ですごめんなさい…
（sedがあるからLinux版が動く？）


# 注意:誤動作を起こすパターン
コードではなくローマ字そのものに関してですが…
以下のような単語はローマ字で区別されないため、間違った区切り結果が得られる可能性があります。

## 「ん」+「ア行」 or 「ナ行」
「全員」も「是認」も`zenin`です。
当コードはすべて「ん」+「ア行」（「全員」の方）と解釈します。

```bash
$ echo "zenin" | bash ./roman2phoneme_ignoreQ.sh 
z e n i n
```

## 「ん」+ヤ行or ニャ行
「記入」も「金融」も`kinyu`です。
当コードではすべて「ニャ行」(「金融」の方)と解釈します。

```bash
$ echo "kinyu" | bash ./roman2phoneme_ignoreQ.sh 
k i ny u 
```

選んだパターンに特に意味はありません。~~実装したらこうなってた~~


# ちょっとバージョン違い
## 撥音「ん」をNにする
「ん」を大文字の`N`にすることで、ナ行の子音（orマ行の子音）と撥音を区別します。

```bash
$  echo "namba dempa" | bash ./roman2phoneme_withN.sh 
n a N b a d e N p a
```

## 促音をQにする
元のバージョンでは、促音を`Q`で表し、それ以外の子音と区切って出力していました。

```bash
$ echo "shikkari zasshi matchi rakkyo" | bash ./roman2phoneme.sh
sh i Q k a r i z a Q sh i m a Q ch i r a Q ky o
```

このバージョンでは、促音も含めて子音はそのままひとかたまりで出力します。

```bash
$ echo "shikkari zasshi matchi rakkyo" | bash ./roman2phoneme_ignoreQ.sh 
sh i kk a r i z a ssh i m a tch i r a kky o
```

# 正規表現の中身
(PowerShell版、Bash版どちらも同じなので、Bash版で説明します)

ご覧の通り、正規表現を何重にも使って文字列を変換しています。

```bash:roman2phoneme.sh
#!/bin/bash

# 母音の前後にスペースを入れる
sed -r "s/([aiueo])/ \1 /g" |
# 撥音「ん」の前後にスペースを入れる
sed -r "s/([nm])([^y])/ \1 \2 /g" |
# 促音「っ」を"Q"に置き換え前後にスペースを入れる(チャ行以外)
sed -r "s/([^ \f\n\r\taiueo])(\1)/ Q \2/g" |
# 促音「っ」を"Q"に置き換えの前後にスペースを入れる(チャ行)
sed -r "s/tch/Q ch/" |
# 空白が連続する場合一つだけにする(見た目をきれいに)
sed -r "s/[ \f\n\r\t]+/ /g"
```

## 母音の前後にスペースを入れる
まずは母音と子音を区切ります。ローマ字の母音は`aiueo`の5文字だけなので、これらをキャプチャして前後にスペースを入れます。

```bash
$ sed -r "s/([aiueo])/ \1 /g"
```

## 撥音「ん」の前後にスペースを入れる
次に「ん」です。「ん」には母音が無いため、上の変換だけでは「ん」と別の子音がくっついたままになっています。

```bash
$ echo "genki" | sed -r "s/([aiueo])/ \1 /g"
g e nk i 
```

そのため、子音の先頭が`n`と`m`(`b`,`m`,`p`の前では、「ん」は"m"になります！)の場合、スペースで区切ります。

```bash
sed -r "s/([nm])([^y])/ \1 \2 /g"
```

### "N"に置き換える場合

マッチした文字そのまま出す代わりに`N`に置き換えます。

ただし、この場合置換は**最初にやる必要があります**。

（母音のスペース区切りより先に変換しないとマ行が誤って「N+母音」になってしまう）

```bash
sed -r "s/([nm])([^yaiueo])/ N \2 /g"
```

## 促音「っ」を"Q"に置き換える

促音は、子音の先頭文字の繰り返しで表現されます。ただし、チャ行だけ例外で`tch`となります。
チャ行とそれ以外両方に対応するため、正規表現を2回かませます。

```bash
# チャ行以外
sed -r "s/([^ \f\n\r\taiueo])(\1)/ Q \2/g" |
# チャ行
sed -r "s/tch/Q ch/"
```

## 連続する空白を一つだけにする
区切りのために重複してスペース追加してしまう場所があるため、スペースを一つだけに減らします。

```bash
sed -r "s/[ \f\n\r\t]+/ /g"
```

# おわりに
ローマ字って意外と複雑なんだなあ…（小並）

「この文字列だと上手くいかないぞオイ」等ありましたらコメントで教えていただけるとありがたいです。