Pythonで正規表現を使う方法です。
今回は数字について書きました。
○○以上○○以下とか、郵便番号や電話番号のパターンチェックなどを例に紹介しています。
目次(リンク)
Pythonの正規表現には、reモジュールを使う
正規表現は英語でregexとか、regular expressionと書きます。
そして、reはその略ですね。
文字列が部分一致しているかどうかは、reモジュールのmatch関数を使います。
一部分だけじゃなくて全部一致しているかどうか確認するなら、fullmatch関数です。
re.match(パターン, 文字列)
re.fullmatch(パターン, 文字列)
パターンには、パターン用の書き方があります。
raw文字列というヤツです。
- 次のようにraw文字列を使う
- r’ここに正規表現の文字列を書く’
以降は、いろんな数字のパターンを紹介します。
○○桁の数字を指定する(半角、全角)
1桁の数字や2桁以上の数字を指定してみます。
1桁の数字
まずは1桁の数字から。
変数regexにパターンを格納し、match関数で判定した結果をbool関数でTrueなのかFalseなのか判定してみました。
判定結果をprint関数で表示です。
1 2 3 4 5 6 7 8 9 10 11 |
import re #1桁の数字 regex = r'([0-9])' regex2 = r'(\d)' #一致するかどうか見てみる print(bool(re.match(regex, '7'))) #半角7 print(bool(re.match(regex, '7'))) #全角7 print(bool(re.match(regex2, '5'))) #半角5 print(bool(re.match(regex2, '5'))) #全角5 |
2通りの書き方を使ってみました。
さっそく実行してみます。
半角の数字なら、どちらも同じようにTrueとなりました。
しかし全角になると、判定結果が違うようです。
全角と半角を区別しつつ、全角の数字について判定するなら、[0-9]のように書きます。
[0-9] :1桁の数字、全角半角の区別あり
[0-9]:1桁の数字、全角半角の区別あり
\d :1桁の数字、半角全角の区別なし
任意の桁の数字
3桁や5桁の数字で試してみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import re #3桁の数字 regex = r'([0-9]{3})' #5桁の数字 regex2 = r'(\d{5})' #一致するかどうか見てみる print(bool(re.match(regex, '789'))) #半角789 print(bool(re.match(regex, '789'))) #全角789 print(bool(re.match(regex2, '56789'))) #半角56789 print(bool(re.match(regex2, '56789'))) #全角56789 |
{n}はn回繰り返すという意味です。
{3}で1桁の数字を3回繰り返すわけです。
実行してみると・・・。
結果は1桁の場合と同じようになりました。
18以上65以下の場合
1桁の数字なら、3以上7以下だったら[3-7]のように書けます。
では2桁以上の場合どうなるか。
まずは18以上65以下を例に書いてみます。
1 2 3 4 5 6 7 8 9 10 11 |
import re #3桁の数字 regex = r'(1[8-9]|[2-5][0-9]|6[0-5])' #一致するかどうか見てみる print('17:'+str(bool(re.match(regex, '17')))) print('18:'+str(bool(re.match(regex, '18')))) print('41:'+str(bool(re.match(regex, '41')))) print('65:'+str(bool(re.match(regex, '65')))) print('66:'+str(bool(re.match(regex, '66')))) |
3つに分けて書くことができます。
10の位が1のとき、18と19のどちらかです。
なので、1[8-9]と表します。
20~59は[2-5][0-9]。
ここは表現しやすいところです。
60以上は、6[0-5]と表します。
この3つのどれかに当てはまれば18以上65以下なので、~または~の「|」で繋げています。
では18、65など、中央値、境界値を見てみましょう。
中央値は当然ながら、境界値もしっかり判定できています。
桁数の範囲を指定する
今度は桁数の範囲を指定してみます。
1桁のところでも{n}の書き方を使いました。
範囲指定はこれを使っていきます。
○桁から○桁の数字
{最小値, 最大値}
3桁から7桁なら、カンマ区切りで{3,7}と書きます。
1 2 3 4 5 6 7 8 9 10 11 12 |
import re #3~7桁の数字 regex = r'([0-9]{3,7})' #一致するかどうか見てみる print(bool(re.match(regex, '01'))) #2桁 print(bool(re.match(regex, '012'))) #3桁 print(bool(re.match(regex, '1414213'))) #7桁 print(bool(re.match(regex, '14142135'))) #8桁 print(bool(re.fullmatch(regex, '1414213'))) #8桁 print(bool(re.fullmatch(regex, '14142135'))) #8桁 |
実行してみると・・・。
match関数の場合、3桁以上なら8桁の数字でもマッチしてしまいました。
8桁の中に3~7桁の部分があるからです。
fullmatch関数の場合、7桁ならTrue、8桁でFalseとなりました。
完全一致かどうか確認できています。
○○桁以下の数字
{, 最大値}
「○○以上」のところを消して、「○○以下」だけ書きます。
7桁以下なら、{,7}。
1 2 3 4 5 6 7 8 9 10 11 12 |
import re #7桁以下の数字 regex = r'([0-9]{,7})' #一致するかどうか見てみる print(bool(re.match(regex, '01'))) #2桁 print(bool(re.match(regex, '012'))) #3桁 print(bool(re.match(regex, '1414213'))) #7桁 print(bool(re.match(regex, '14142135'))) #8桁 print(bool(re.fullmatch(regex, '1414213'))) #7桁 print(bool(re.fullmatch(regex, '14142135'))) #8桁 |
match関数、fullmatch関数それぞれ実行してみます。
7桁以下の場合、どちらもTrueになりました。
8桁でも、match関数なら7桁以下の部分が含まれるのでTrueとなりますが、fullmatch関数は8桁だとFalseになっています。
○○桁以上の数字
{最小値, }
「○○以下」のところを消して、「○○以上」だけ書きます。
3桁以上なら、{3, }。
1 2 3 4 5 6 7 8 9 |
import re #3桁以上の数字 regex = r'([0-9]{3,})' #一致するかどうか見てみる print(bool(re.match(regex, '01'))) #2桁 print(bool(re.match(regex, '012'))) #3桁 print(bool(re.match(regex, '1414213'))) #7桁 |
3桁以上のパターンで、match関数を使ってみました。
2桁の場合False、3桁以上でTrueとなりました。
組み合わせて使ってみる
郵便番号や電話番号を例に、パターンが一致しているか判定してみます。
郵便番号の形式かどうか確認する
日本の郵便番号は、3桁の数字と4桁の数字をハイフンで繋いだ文字列です。
桁数が足りなかったり、ハイフンなし、正しい郵便番号の形式、桁数オーバーの4つをmatch関数で判定してみました。
また、fullmatch関数で、一致している場合と桁数が多い場合を見てみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import re #郵便番号 regex_post = r'([0-9]{3}-[0-9]{4})' #match関数で確認 print(bool(re.match(regex_post, '11-4567'))) #間違った郵便番号 print(bool(re.match(regex_post, '1234567'))) #間違った郵便番号 print(bool(re.match(regex_post, '123-4567'))) #正規の郵便番号 print(bool(re.match(regex_post, '123-45678'))) #間違った郵便番号 #fullmatch関数で確認 print(bool(re.fullmatch(regex_post, '123-4567'))) #正規の郵便番号 print(bool(re.fullmatch(regex_post, '123-45678'))) #間違った郵便番号 |
実行します。
match関数だと桁数が多い場合にもTrueとなりました。
fullmatch関数なら、完全一致のみTrueとなりました。
携帯電話の形式かどうか確認する
郵便番号の例でだいたい分かってしまったと思いますが、携帯電話でもやってみます。
携帯電話は、先頭3桁が070、080、090の3通り。
ハイフン有り無しは、-?でどちらもOKとなります。
携帯番号をmatch関数で確認
ではmatch関数から見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import re #携帯電話番号 regex_post = r'(0[7-9]0-?[0-9]{4}-?[0-9]{4})' #一致するかどうか見てみる print(bool(re.match(regex_post, '03-1234-5678'))) #固定電話番号 print(bool(re.match(regex_post, '0120-000-000'))) #フリーダイヤル print(bool(re.match(regex_post, '817012345678'))) #国際携帯電話番号 print('-----------') print(bool(re.match(regex_post, '07012345678'))) #携帯電話番号ハイフンなし print(bool(re.match(regex_post, '0801234567'))) #1桁足りない print(bool(re.match(regex_post, '090123456789'))) #1桁多い print('-----------') print(bool(re.match(regex_post, '070-1234-5678'))) #携帯電話番号ハイフンあり print(bool(re.match(regex_post, '080-1234-56789'))) #1桁多い print(bool(re.match(regex_post, '090-1234-567'))) #1桁足りない |
9通りの例を書いてみました。
070などで始まっていない場合は全部Falseの判定です。
11桁の場合はTrueになりますが、12桁でもFalseにはなりません。
-?[0-9]{4}のところで、5桁続いても4桁は部分一致しているためです。
やはりmatch関数ではムリがありますね。
fullmatch関数で確認してみる
match関数で書いていたところを、全部fullmatch関数に換えてみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import re #携帯電話番号 regex_post = r'(0[7-9]0-?[0-9]{4}-?[0-9]{4})' #一致するかどうか見てみる print(bool(re.fullmatch(regex_post, '03-1234-5678'))) #固定電話番号 print(bool(re.fullmatch(regex_post, '0120-000-000'))) #フリーダイヤル print(bool(re.fullmatch(regex_post, '817012345678'))) #国際携帯電話番号 print('-----------') print(bool(re.fullmatch(regex_post, '07012345678'))) #携帯電話番号ハイフンなし print(bool(re.fullmatch(regex_post, '0801234567'))) #1桁足りない print(bool(re.fullmatch(regex_post, '090123456789'))) #1桁多い print('-----------') print(bool(re.fullmatch(regex_post, '070-1234-5678'))) #携帯電話番号ハイフンあり print(bool(re.fullmatch(regex_post, '080-1234-56789'))) #1桁多い print(bool(re.fullmatch(regex_post, '090-1234-567'))) #1桁足りない |
実行してみます。
11桁の携帯番号のところだけ、Trueとなりマッチしていることが分かりました。
まとめ:正規表現で数字の範囲、桁数を指定する方法
まとめるとこんな感じです。
- 正規表現は、reモジュールを使う
- 部分一致の確認はmatch関数
- 完全一致ならfullmatch関数
- パターンはRawで、r’パターン’のように指定する
- 数字の範囲は、[最小値-最大値]
- 桁数の範囲は、{最小桁数, 最大桁数}
- 半端な数字は、~またはの「|」で各パターンを書く
今回は数字のみでやってきました。
英字も混在すると、英字用のパターンも必要になってきますので、また別の記事で書いていきます。