Pythonで正規表現を使ってみよう!
様々なプログラミング言語において、正規表現が活用されています。正規表現とは何でしょうか?
Pythonにおいて、正規表現を実装するため、どんなモジュール・関数が必要でしょうか?実際に、正規表現を使って、文字列から携帯番号を抽出するサンプルコードを解説します。
Pythonで正規表現を使ってみましょう!
正規表現って何?
正規表現とは、文字列内で文字の組み合わせを照合するために用いられるパターンです。英語では、“regular expressions”(REs や regexes または regex patterns)と呼ばれています。
正規表現を使うと、文字列の中から、特定のパターン文字列(e-mailアドレス、電話番号など)を検索し、抽出することができます。
具体的には以下のような処理によく用いられています。
- 文字列のパターンマッチング・置換
- テキスト解析
- データのバリデーション
正規表現の記法
正規表現は、メタ文字と特殊シーケンス、また特殊記号自身を表すためにエスケープが用いられます。
正規表現のメタ文字
正規表現は、いくつかの特別な文字“メタ文字”によって表現されます。メタ文字は、それぞれ意味合いが付与されています。例えば、「$」には、文字列の末尾という意味合いがあります。
文字列“Enjoy your adventure, find more about Japan”において、正規表現パターン「re$」を指定した場合、文字列“adventure”と“more”が抽出されます。
使用頻度の高いメタ文字を列挙します。
メタ文字 | マッチする文字列 | 例 | 抽出文字列 |
---|---|---|---|
. | 改行以外の任意の文字にマッチ | a.c | abc, aac, acc, a1c … |
^ | 文字列の先頭にマッチ | ^ab | abc, abd, ab1 … |
$ | 文字列の末尾にマッチ | yz$ | xyz, yyz, 1yz … |
* | 直前の正規表現を 0 回以上繰り返したものにマッチ | ab* | a, ab, abb, abbb … |
+ | 直前の正規表現を 1 回以上繰り返したものにマッチ | ab+ | ab, abb, abbb … |
? | 直前の正規表現を 0 回か 1 回繰り返したものにマッチ | ab? | a, ab |
{m} | 直前の正規表現をちょうど m 回繰り返したものにマッチ | a{3} | aaa |
{m,n} | 直前の正規表現を m 回から n 回、できるだけ多く繰り返したものにマッチ | a{2,4} | aa, aaa, aaa |
[ ] | 文字の集合を指定する。カッコ内に指定した文字のうち、いずれかの一文字 | [amk][x-z] | a, m, kx, y, z |
A|B | A|B は A と B のいずれかにマッチ | a|b | a, b |
( ) | グループの開始と終了。丸括弧で囲まれた正規表現にマッチ | (xyz)+ | xyz, xyzab |
正規表現の特殊シーケンス
特殊シーケンス | マッチする文字列 | 正規表現での表し方 |
---|---|---|
\d | 任意の数字にマッチ | [0-9] |
\D | 任意の数字以外にマッチ | [^0-9] |
\s | 任意の空白文字にマッチ | [\t\n\r\f\v] |
\S | 任意の空白文字以外にマッチ | [^\t\n\r\f\v] |
\w | 任意の英数字にマッチ | [a-xA-Z0-9_] |
\W | 任意の英数字以外にマッチ | [^a-xA-Z0-9_] |
また、メタ文字と特殊シーケンスなど、特殊文字自体を表現する場合、「¥」でエスケープします。例えば、「.」(ピリオド)を表現する時は、「¥.」と表記しエスケープします。これで、ピリオドを意味します。
その他の特殊文字も、同じ方法でエスケープできます。
pythonで正規表現を使うには
正規表現を実装するには、reモジュールが必要!
Pythonでは、reモジュールをインポートする事によって、正規表現を実装できます。このモジュールには、文字列の検索、置換、連結、分割など、文字列を扱う上で役立つメソッドが実装されており、正規表現にマッチした文字列、またマッチした情報をオブジェクトとして返します。詳しくは、モジュールコンテンツの公式ドキュメントを参照してください。本章では、Pythonで実装するためのモジュールと、各関数の解説を行います。
では、reモジュールをインポートしてみましょう。
import re
簡単ですね。
では、このモジュールに含まれる主な関数やメソッドを見ていきます。
関数 | 処理 | 返り値 |
---|---|---|
match | 先頭で一致するものを検索 | 対応するマッチオブジェクト※ 一致しない場合はNone |
search | 先頭に限らず一致するものを検索 | 対応するマッチオブジェクト※ 一致しない場合はNone |
findall | 一致するもの全てを検索 | マッチする文字列全てのリスト※ 一致しない場合は空のリスト |
finditer | 一致するもの全てを検索 | 対応する全てのマッチオブジェクト※ 一致しない場合はNone |
fullmatch | 完全一致するものを検索 | 対応するマッチオブジェクト※ 一致しない場合はNone |
sub | 一致した文字列を置換 | 置換後の文字列 |
match 関数
re.match(pattern, string, flags=0)
任意文字列の“先頭”で正規表現パターンにマッチした場合、対応するマッチオブジェクトを返します。文字列が、正規表現パターンにマッチしない場合、Noneを返します。
この関数は、任意文字列の“先頭”に抽出ワードがあるかどうかを判定します。
文字列全体で、正規表現パターンにマッチさせたい場合は、次のsearch関数を使用します。
search 関数
re.search(pattern, string, flags=0)
任意文字列全体を走査し、正規表現パターンがマッチする最初の場所を探し、対応するマッチオブジェクト を返します。正規表現パターンがマッチしない場合、None を返します。
この関数は、任意文字列中に、抽出ワードがあるかどうかを判定します。文字列全体で、正規表現パターンを“複数”マッチさせたい場合は、次のfindall関数を使用します。
findall 関数
re.findall(pattern, string, flags=0)
任意文字列中全体を走査し、正規表現パターンにマッチする文字列を、見つかった順番で、リストとして返します。
複数のe-mailアドレスや電話番号をリストとして抽出する場合、とても役に立つ関数です。
finditer 関数
re.findall(pattern, string, flags=0)
任意文字列中全体を走査し、正規表現パターンにマッチした場合、対応するマッチオブジェクト全てを返します。正規表現パターンがマッチしない場合、None を返します。findall
では返り値がリストですが、finditer
ではマッチオブジェクトが返ってくるため、開始位置、終了位置も取得することができます。
fullmatch 関数
re.fullmatch(pattern, string, flags=0)
任意文字列の全体が正規表現のパターンに完全一致した場合、対応するマッチオブジェクトを返します。正規表現パターンがマッチしない場合、None を返します。
sub 関数
re.sub(pattern, repl, string, count=0, flags=0)
この関数は、検索だけでなく置換を行います。任意文字列中全体を走査し、正規表現パターンにマッチしている箇所全てを任意の文字列に置き換えて返します。
正規表現を使った具体事例
実際に、サンプルデータから、正規表現パターンを使って、携帯番号を抽出していきましょう。
使用するサンプルデータは、次のとおりです。
幌呂 〒 085-1199 北海道阿寒郡鶴居村幌呂西 Tel 090-0065-2150
鶴居 〒 085-1299 北海道阿寒郡鶴居村鶴居西Tel 080-0064-2120
下久著路簡易郵便局 〒 085-1362 北海道阿寒郡鶴居村下久箸呂北 Tel 090-0064-2160
旭川新富郵便局 〒 070-0002 北海道旭川市新富二条 Tel 080-0026-3902
このサンプルデータから、携帯番号(090-0065-2150, 080-0064-2120, 090-0064-2160, 080-0026-3902)
を抽出します。
サンプルコード
【使用例】
import re
sample_data = "幌呂 〒 085-1199 北海道阿寒郡鶴居村幌呂西 Tel 090-0065-2150, 鶴居 〒 085-1299 北海道阿寒郡鶴居村鶴居西Tel 080-0064-2120, 下久著路簡易郵便局 〒 085-1362 北海道阿寒郡鶴居村下久箸呂北 Tel 090-0064-2160, 旭川新富郵便局 〒 070-0002 北海道旭川市新富二条 Tel 080-0026-3902"
mobile_phone_list = re.findall('[0-9]{3}-[0-9]{4}-[0-9]{4}', sample_data)
if mobile_phone_list:
print (mobile_phone_list)
【実行結果】
['090-0065-2150', '080-0064-2120', '090-0064-2160', '080-0026-3902']
正規表現のコード解説
+演算子を使うとリストを結合することができます。
サンプルコードの解説です。
1行目:import re:reモジュールのインポートを行います。
2行目:サンプル文字列データを、sample_data
に代入します。
3行目:findall関数を使用し、携帯番号を抽出します。
第一引数に、携帯電話番号の正規表現パターンを代入します。
第二引数に、サンプル文字列データを代入します。
正規表現パターンにマッチする文字列が、mobile_phone_list
リストに格納されます。
4~5行目:mobile_phone_list
リストに格納された携帯番号出力します。
まとめ
いかがでしたか?正規表現の蓋を開けてみると、意外と簡単だったのではないでしょうか?今回は、Pythonで正規表現を実装するため、必要なモジュール・関数を解説しました。
実践で、このモジュールを使いこなし、文字列の検索、置換、連結、分割を、効率よく行いましょう!