Pythonで使える正規表現まとめ
O'REILLYの著書『退屈なことはPythonにやらせよう』で「正規表現」について記載されているところをまとめたノートです。
正規表現はCtrl-Fのテキスト検索でも気軽に使えて大変便利なので、以下のまとめはpython3での正規表現の初歩的な使い方をまとめたものですが、知らなかった人は見てみてもいいかもです。
要点¶
メタ文字¶
?
は、直前のグループの0回か1回の出現にマッチする。(任意のマッチ)*
は、直前のグループの0回以上の出現にマッチする。+
は、直前のグループの1回以上の出現にマッチする。{n}
は、直前のグループのn回の出現にマッチする。{n,}
は、直前のグループのn回以上の出現にマッチする。{,m}
は、直前のグループの0~m回の出現にマッチする。{n,m}?
、?
、+?
は直前のグループの非貪欲マッチを行う。
文字集合¶
\d
:0~9の数字\D
:0~9の数字以外\w
:文字、数字、下線(単語wordのw)\W
:文字、数字、下線以外\s
:スペース、タブ、改行(空白spaceのs)\S
:スペース、タブ、改行以外
正規表現マッチのまとめ¶
re
モジュールre.compile()
関数search()
メソッドgroup()
メソッドfindall()
メソッド
実践¶
#! python 3
#正規表現モジュールのインポート
import re
'\d'は1文字の数字を表す正規表現¶
\d
を用いて、あるtextから、電話番号パターンにマッチする部分を検索しましょう。
re.compile()
に正規表現パターンを表す文字列を渡すと、Regexオブジェクトが返ります。
phone_num_regex = re.compile(r'\d\d\d-\d\d\d\d-\d\d\d\d')
文字列の前のr
はraw文字列を指定し、文字をエスケープせずに簡潔に表現しています。
search()メソッドとgroup()メソッド¶
Regexオブジェクトのsearch()
メソッドは、渡された文字列の中から正規表現にマッチするパターンが見つかれば、Matchオブジェクトを返します。
Matchオブジェクトにはgroup()
メソッドがあり、実際にマッチしたテキストを返します
mo = phone_num_regex.search('私の電話番号は080-1111-22222です。')
print('電話番号が見つかりました:' + mo.group())
'()'を用いたグルーピング¶
phone_num_regex = re.compile(r'(\d\d\d)-(\d\d\d\d-\d\d\d\d)')
mo = phone_num_regex.search('私の電話番号は080-1000-2000です。')
print(mo.group(0))
print(mo.group(1))
print(mo.group(2))
print(mo.groups())
'|'を使って複数のグループとマッチ¶
例えばr'Batman|Spiderman'
という正規表現は、'Batman'
or'Spiderman'
にマッチします。
hero_regex = re.compile(r'Batman|Spiderman')
mo1 = hero_regex.search('Batman and Yasmizuman')
mo1.group()
両方ある場合は最初に出現したほうが返ります。
mo2 = hero_regex.search('The Spiderman fights Batman and Yasumizuman')
mo2.group()
丸カッコと縦線とを応用¶
yasumizu_regex = re.compile(r'Yasumizu(man|woman|hotel)')
mo = yasumizu_regex.search('Yasumizuman lost his way back to Yasumizuhotel.')
mo.group(1)
'?'を用いた任意のマッチ¶
yasu_regex = re.compile(r'Yasumizu(wo)?man')
mo1 = yasu_regex.search('The Adveture of Yasumizuman')
mo1.group()
mo2 = yasu_regex.search('The Adveture of Yasumizuwoman')
mo2.group()
'*'を用いた0回以上のマッチ¶
yasu_regex = re.compile(r'Yasu(mi)*zu')
mo1 = yasu_regex.search('The Adventure of Yasuzu')
mo1.group()
mo2 = yasu_regex.search('The Adventure of Yasumimimimimimimizu')
mo2.group()
'+'を用いた1回以上のマッチ¶
yasu_regex = re.compile(r'Yasu(mi)+zu')
mo1 = yasu_regex.search('The Adventure of Yasumimimimimizu')
mo1.group()
mo2 = yasu_regex.search('The Adventure of Yasuzu')
mo2 == None
'{}'を用いて繰り返し回数を指定する¶
例:(Ha){3} = (HaHaHa) , (Ha){3,5} = (HaHaHa|HaHaHaHa|HaHaHaHaHa)
ha_regex = re.compile(r'(Ha){3,5}')
mo1 = ha_regex.search('HaHaHaHaHa')
mo1.group()
mo2 = ha_regex.search('Ha')
mo2 == None
貪欲マッチ:ジャガビーは一番長いものをとる。¶
Pythonの正規表現は、デフォルトでは貪欲マッチです。つまり、複数の可能性があると最も長い方にマッチします。
greedy_Ha_regex = re.compile(r'(Ha){3,5}')
mo1 = greedy_Ha_regex.search('HaHaHaHaHaHaHaHaHaHaHa')
mo1.group()
非貪欲マッチ:遠慮して一番短いものをとる¶
閉じカッコの後に?
nongreedy_Ha_regex = re.compile(r'(Ha){3,5}?')
mo2 = nongreedy_Ha_regex.search('HaHaHaHaHaHaHaHaHaHaHa')
mo2.group()
findall()メソッド¶
search()
が最初に見つかった文字列を返すのに対し、findall()
は見つかったすべての文字列を返します。
findall()
はタプルのリストを返すことに注意。
phone_num_regex = re.compile(r'\d\d\d-\d\d\d\d-\d\d\d\d')
phone_num_regex.findall('Cell: 415-5555-9999 Work: 212-5555-0000')
phone_num_regex = re.compile(r'(\d\d\d)-(\d\d\d\d)-(\d\d\d\d)')
phone_num_regex.findall('Cell: 415-5555-9999 Work: 212-5555-0000')
続きはありますが、あまり出しすぎるとネタが無くなるので、今回はここまでにしておきます。 また書きます。
上記の内容をうまく利用して、自分で電子メールアドレスの正規表現を作ってみてもおもしろいと思います。
正規表現について、さらに詳しく¶
- 前の記事 : 論文抄読で便利なサイト
- 次の記事 : 超高速次元圧縮アルゴリズムUMAP
- 関連記事 :