目次
1.はじまり
研究室で「数字を英語読みに変換するプログラムの実装がだるい」という話が出たので、面白そうだから私も実装してみるかとやっているところです。
さて、英語読みにするには、数字と読み方が対応したデータが必要です。プログラム内に記述してもいいのですが、なんだか汚いコードになるのでjsonファイルに書き込むことにしました。
しかし、jsonの形式で書くのもめんどくさい。じゃあネットから取ってくるかと思ってもjsonの形式で書かれていない。
そういうことで、ネットから取ってきたものを正規表現を使って置換してみました。
2.やりたいこと
はじめは次のような状態です。
{
1
"one"
2
"two"
3
"three"
4
"four"
5
"five"
6
"six"
7
"seven"
8
"eight"
9
"nine"
10
"ten"
11
"eleven"
12
"twelve"
13
"thirteen"
14
"fourteen"
15
"fifteen"
16
"sixteen"
17
"seventeen"
18
"eighteen"
19
"nineteen"
20
"twenty"
30
"thirty"
40
"forty"
50
"fifty"
60
"sixty"
70
"seventy"
80
"eighty"
90
"ninety"
}
(数値を英語表現にするライブラリより。)
前処理としてwhen部分は一括置換で削除しました。
これをjsonの形式に書き換えます。つまり、
"1":"one",
のようにしたいです。
3.調べたこと
正規表現は使ったことがないので調べました。
4.やったこと
まずは数字側を書き換えます。やりたいことは次のとおりです。
"1":
数字にダブルクオーテーションをつけて、更にコロンをつけたいです。
次のような置換を行います。
検索:
(\d{1,2})
置換:
"$1":
\dはすべての数字を表し、中括弧では直前の最小桁数と最大桁数を指定できます。
また、括弧で囲んだ部分では、検索時に用いた文字列をそのまま置換のときに用いることができます。用いる場合、置換条件では$1のように記述します。
1と書かれている通り、2つ目のマッチした文字列などでは$2のようになることもあります。
さて、これで数字部分はできました。
次に文字列の部分の後ろにカンマをつけたいです、
"1": "one",
一括置換だと全部にカンマが付きますが、ケツカンマだけ削除すればjsonの記述としては正しくなるので、ケツカンマ削除だけ手作業で行います。
検索:
(\D{5,14})
置換:
$1,
\Dは数字以外を表します。桁数については、最小桁数4桁以下にすると、2行目の1までの部分がマッチングしてしまうため、5桁に設定しています。最大桁数に関しては、空白部分も合わせて最も長い文字列であるseventeenに合わせて14桁にしています。
結果的に次のようになりました。
{
"1":
"one",
"2":
"two",
"3":
"three",
"4":
"four",
"5":
"five",
"6":
"six",
"7":
"seven",
"8":
"eight",
"9":
"nine",
"10":
"ten",
"11":
"eleven",
"12":
"twelve",
"13":
"thirteen",
"14":
"fourteen",
"15":
"fifteen",
"16":
"sixteen",
"17":
"seventeen",
"18":
"eighteen",
"19":
"nineteen",
"20":
"twenty",
"30":
"thirty",
"40":
"forty",
"50":
"fifty",
"60":
"sixty",
"70":
"seventy",
"80":
"eighty",
"90":
"ninety"
}
ただ、これだと無駄に改行されていて読みにくいです。そのため、改行コードを消してあげます。
しかし、すべての改行コードを削除するとすべてが1行に詰まってしまうので、数字の書かれている部分の一番うしろにある改行コードを削除します。
今回の場合は、数字が書かれている部分の改行コードの前には必ずコロンがあるため、次のような条件で検索をし、置換をします。
検索:
:\n
置換:
:
こうすることで次のようにできました。
{
"1": "one",
"2": "two",
"3": "three",
"4": "four",
"5": "five",
"6": "six",
"7": "seven",
"8": "eight",
"9": "nine",
"10": "ten",
"11": "eleven",
"12": "twelve",
"13": "thirteen",
"14": "fourteen",
"15": "fifteen",
"16": "sixteen",
"17": "seventeen",
"18": "eighteen",
"19": "nineteen",
"20": "twenty",
"30": "thirty",
"40": "forty",
"50": "fifty",
"60": "sixty",
"70": "seventy",
"80": "eighty",
"90": "ninety"
}
これでもいい感じですが、コロンと後ろの文字列の間が空きすぎてて嫌な感じです。そのため、この部分を空白1つにします。
この部分の空白は3つですが、単純に置換しようとすると数字部分の前、つまり行頭の空白も置換してしまいます。
そのため、次のような条件になりました。
検索:
??("\D)
置換:
$1
ダブルクオーテーションまででは数字部分も一致してしまうため、その後ろに半角英数でないという条件をつけて、数字部分が一致しないようにしています。
最後に、行頭の空白を2つにして終わりです。こちらの置換は正規表現を用いなくてもできるため、条件は省略します。
また、行頭の空白を2つにする理由としては、jsonでのインデントは慣例的に空白2つか4つらしいですが、今回は無視します。
完成したjsonファイルは次のようになりました。
{
"1": "one",
"2": "two",
"3": "three",
"4": "four",
"5": "five",
"6": "six",
"7": "seven",
"8": "eight",
"9": "nine",
"10": "ten",
"11": "eleven",
"12": "twelve",
"13": "thirteen",
"14": "fourteen",
"15": "fifteen",
"16": "sixteen",
"17": "seventeen",
"18": "eighteen",
"19": "nineteen",
"20": "twenty",
"30": "thirty",
"40": "forty",
"50": "fifty",
"60": "sixty",
"70": "seventy",
"80": "eighty",
"90": "ninety"
}
5.おわりに
正規表現はずっと役に立つというツイートを最近見かけた気がします。
結構正規表現を使う機会は多そうなので、覚えておこうと思います。
正規表現の学習には様々なサイトがありますが、Regex Crosswordという正規表現でクロスワードパズルを行うサイトなどもあったりします。
こういうのを利用しつつ学べると楽しそうです。
この記事を執筆してる時点では、本来の目的の達成度合いは、数値を整数部と小数部に分割するところまで実装して、C++でjsonファイルを操作する記事を読んだところで止まっています。
まだまだ先は長い。
6.参考文献
基本的な正規表現一覧←めっちゃ便利なチートシート
数値を英語表記にするライブラリ←データ利用