『金額』の正規表現つくってみた


結論

pythonによる『金額』の正規表現はこちらです。

円終わりバージョンは以下です。

pattern = r'^(0|[1-9]\d*|[1-9]\d{0,2}(,\d{3})+)円'

# OK
# 0円
# 1,000円
# 100円
# 12345円
# 2000円
# 1234円
# 1000円

# NG
# 0,000円
# 000円
# ,円
# 10,00円

¥(円マーク)始まりバージョンは以下です。

pattern = r'^¥(0|[1-9]\d*|[1-9]\d{0,2}(,\d{3})+)$'

# OK
# ¥0
# ¥1,000
# ¥100
# ¥12345
# ¥2000
# ¥1234
# ¥1000

# NG
# ¥0,000
# ¥000
# ¥,
# ¥10,00

準備

環境はGoogle Colaboratoryを使用します。
Pythonのバージョンは以下です。

import platform
print("python " + platform.python_version())
# python 3.6.9

正規表現のチェックツールは以下を使用しました。
https://regex101.com/
こちらで確認しながら正規表現を作成し、コードに実装していきます。

また、Pythonの正規表現全般については、こちらがわかりやすいです。
https://qiita.com/luohao0404/items/7135b2b96f9b0b196bf3

金額の正規表現をつくってみよう

円終わりバージョン

早速コードを書いていきましょう。
まずは、正規表現を使うためのライブラリをインポートします。

import re

ではまず、
1000円
という文字列とマッチする正規表現をつくってみます。

pattern = r'1000円'

もちろん、これは完全一致なのでマッチします。
コードで確かめてみましょう。

pattern = r'1000円'
string = r'1000円'
prog = re.compile(pattern)
result = prog.match(string)
if result:
    print(result.group())
# 1000円

マッチした文字列が表示されています。
以降は簡単のために、正規表現のpatternのみ記載します。

金額には、「1000円」以外にも、「2000円」や「1234円」などがあります。
これらにもマッチする正規表現は以下です。

pattern = r'\d\d\d\d円'

使用した正規表現は以下です。

文字 説明
\d 任意の数字
マッチする文字列
\d\d\d\d 1000, 2000, 1234

上の正規表現は、もっと簡単に表すことができます。

pattern = r'\d{4}円'

新たに使用した正規表現は以下です。

文字 説明
{m} 直前の文字のm回の繰り返し
マッチする文字列
\d{4} 1000, 2000, 1234

しかしこれでは、「100円」や「12345円」など4桁以外の金額をとれません。
どんな桁数でもとれるように対応しましょう。

修正した正規表現は以下になります。

pattern = r'\d+円'

新たに使用した正規表現は以下です。

文字 説明
+ 直前の文字の1回以上の繰り返し
マッチする文字列
\d+ 1000, 100, 12345

しかしこれでは、「1,000円」のような「,(カンマ)」が入った文字列はとれません。
数字だけでなく、カンマも許容するようにします。

修正した正規表現は以下になります。

pattern = r'[\d,]+円'

新たに使用した正規表現は以下です。

文字 説明
[abc] a,b,cのいずれかの文字
マッチする文字列
[\d,] 数字もしくは,(カンマ)

また、以下の正規表現も使用しました。

文字 説明
+ 直前の文字の1回以上の繰り返し
マッチする文字列
[\d,]+ 数字もしくは,(カンマ)の1回以上の繰り返し

これで、数字と,(カンマ)に対応できました。

しかしこれでは、「,円」や「10,00円」といった、カンマの位置が適切でない文字列もとってしまいます。
カンマは「1,000円」や「1,000,000円」といったように、3桁ごとに入るよう修正します。

修正した正規表現は以下になります。

pattern = r'\d{1,3}(,\d{3})+円'

新たに使用した正規表現は以下です。

文字 説明
{m,n} 直前の文字の、m回以上n回以下の繰り返し
マッチする文字列
\d{1,3} 数字の1回以上3回以下の繰り返し

また、以下の正規表現も使用しました。

文字 説明
(abc) abcという文字列を1かたまりとして扱う
マッチする文字列
(,\d{3}) 「,000」のような、「,(カンマ)」と数字3文字を1かたまりとして扱う

こうすると、今までとれていたカンマなしの文字列がとれなくなります。
数字のみのものも取れるよう修正します。

pattern = r'(\d+|\d{1,3}(,\d{3})+)円'

新たに使用した正規表現は以下です。

文字 説明
(abc|efg) abcもしくはefgのいずれかの文字列
マッチする文字列
(\d+|\d{1,3}(,\d{3})+) 1000, 1,000

しかしこれでは、「0,000円」や「000円」といった、0始まりの文字列もとってしまいます。

修正した正規表現は以下になります。

pattern = r'([1-9]\d*|[1-9]\d{0,2}(,\d{3})+)円'

新たに使用した正規表現は以下です。

文字 説明
[a-c] a,b,cのいずれかの文字
マッチする文字列
[1-9] 1~9(0を除く数字)

また、以下の正規表現も使用しました。

文字 説明
* 直前の文字の0回以上の繰り返し
マッチする文字列
\d* 数字の0回以上の繰り返し

これで、0始まりの文字列は除外できました。
ただし、0円だけは許容しなければいけないので、これを加えます。

pattern = r'^(0|[1-9]\d*|[1-9]\d{0,2}(,\d{3})+)円'

新たに使用した正規表現は以下です。

文字 説明
^ 文字列の先頭

「^(ハット)」をつけないと、「0,000円」などの「0円」を部分一致でとってしまいます。

¥始まりバージョン

金額には、円で終わるものだけでなく¥(円マーク)から始まる表記のものもあるので、こちらの正規表現もつくっておきましょう。
先程の正規表現で、最後の「円」を消して最初に「¥」をつけます。

pattern = r'^¥(0|[1-9]\d*|[1-9]\d{0,2}(,\d{3})+)'

ただし、これだと「¥1,000」の「¥1」を部分一致でとってしまいます。
修正したものは以下です。

pattern = r'^¥(0|[1-9]\d*|[1-9]\d{0,2}(,\d{3})+)$'

新たに使用した正規表現は以下です。

文字 説明
$ 文字列の末尾

$を最後につけることで、部分一致でとるのを防いでいます。

まとめ

今回は、Pythonを使って『金額』の正規表現をつくってみました。

日付や時刻、金額といった、ある程度パターンが決まった文字列は正規表現との相性が良いです。
色々な文字列を正規表現で取り出してみて下さい。