re.match() / re.search() / re.fullmatch()
| 対応: | re.match() / re.search() | Python 2(2000) |
|---|---|---|
| fullmatch() | Python 3.4(2014) |
正規表現を使った文字列のパターンマッチングを行う関数です。文字列が特定のパターンに一致するかを判定したり、一致した部分を取り出したりできます。
構文
import re # 文字列の先頭でパターンにマッチするか調べる m = re.match(パターン, 文字列) # 文字列全体からパターンにマッチする部分を探す m = re.search(パターン, 文字列) # 文字列全体がパターンに完全一致するか調べる m = re.fullmatch(パターン, 文字列) # マッチオブジェクトから一致した文字列を取得する m.group() # マッチ全体を返す m.group(1) # 1番目のキャプチャグループを返す m.groups() # 全グループをタプルで返す
関数一覧
| 関数 / メソッド | 概要 |
|---|---|
| re.match(pattern, string) | 文字列の先頭でパターンにマッチするか調べます。先頭以外にパターンがあってもマッチしません。 |
| re.search(pattern, string) | 文字列全体を検索してパターンにマッチする最初の位置を見つけます。先頭以外でもマッチします。 |
| re.fullmatch(pattern, string) | 文字列全体がパターンに完全一致する場合のみマッチします。 |
| m.group() | マッチした文字列全体を返します。引数に整数を指定するとそのキャプチャグループの文字列を返します。 |
| m.groups() | 全キャプチャグループの文字列をタプルで返します。 |
| m.group('名前') | 名前付きキャプチャグループの文字列を返します。 |
| m.start() / m.end() | マッチした範囲の開始・終了インデックスを返します。 |
サンプルコード
match_search_basic.py
import re
name = '碇シンジ'
email = 'shinji@nerv.jp'
m = re.match(r'\w+', name)
if m:
print(m.group())
m2 = re.search(r'@[\w.]+', email)
if m2:
print(m2.group())
m3 = re.fullmatch(r'[a-z]+@[\w.]+', email)
print(bool(m3))
実行すると次のように出力されます。
python3 match_search_basic.py 碇シンジ @nerv.jp True
match_search_groups.py
import re
profile = '綾波レイ: 2015-01-30'
m = re.search(r'(\d{4})-(\d{2})-(\d{2})', profile)
if m:
print(m.group())
print(m.group(1))
print(m.group(2))
print(m.groups())
pattern = r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})'
m2 = re.search(pattern, profile)
if m2:
print(m2.group('year'))
print(m2.group('month'))
実行すると次のように出力されます。
python3 match_search_groups.py
2015-01-30
2015
01
('2015', '01', '30')
2015
01
match_search_email.py
import re
emails = [
'asuka@nerv.jp',
'not-an-email',
'misato@nerv.jp',
]
pattern = re.compile(r'[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}')
for email in emails:
if pattern.fullmatch(email):
print(email + ': 有効')
else:
print(email + ': 無効')
実行すると次のように出力されます。
python3 match_search_email.py asuka@nerv.jp: 有効 not-an-email: 無効 misato@nerv.jp: 有効
よくあるミス
よくあるミス1: match()が先頭以外にマッチしない
『re.match()』は文字列の先頭からしかマッチしません。文字列の途中にパターンがある場合は必ず失敗します。文字列全体を検索したい場合は『re.search()』を使います。
mistake1_ng.py
import re log = '[ERROR] 渚カヲルのログ: 接続失敗' m = re.match(r'ERROR', log) print(m)
実行すると次のように出力されます。
python3 mistake1_ng.py None
mistake1_ok.py
import re
log = '[ERROR] 渚カヲルのログ: 接続失敗'
m = re.search(r'ERROR', log)
if m:
print(m.group())
実行すると次のように出力されます。
python3 mistake1_ok.py ERROR
よくあるミス2: Noneのままgroup()を呼ぶとAttributeErrorになる
『re.match()』や『re.search()』はマッチしなかった場合に『None』を返します。戻り値を if 文で確認せずに直接『group()』を呼ぶと『AttributeError』が発生します。
mistake2_ng.py
import re
text = '葛城ミサトへの連絡はメールで'
m = re.search(r'\d{3}-\d{4}-\d{4}', text)
print(m.group())
実行すると次のように出力されます。
python3 mistake2_ng.py AttributeError: 'NoneType' object has no attribute 'group'
mistake2_ok.py
import re
text = '葛城ミサトへの連絡はメールで'
m = re.search(r'\d{3}-\d{4}-\d{4}', text)
if m:
print(m.group())
else:
print('マッチなし')
実行すると次のように出力されます。
python3 mistake2_ok.py マッチなし
概要
『re.match()』は文字列の先頭のみを調べ、『re.search()』は文字列全体を検索します。先頭かどうかに関わらずパターンを探したい場合は『re.search()』を使います。マッチに失敗した場合はどちらも『None』を返すため、戻り値を if 文で確認してからグループを取り出す必要があります。
正規表現パターンにはPythonの生文字列(『r"..."』)を使うことが推奨されています。生文字列を使うとバックスラッシュをエスケープせずに書けるため、パターンが読みやすくなります。
日本語などのUnicode文字を含む文字列を扱う場合でも、Pythonの正規表現はデフォルトでUnicode対応のため、PHPの『/u』修飾子のような追加設定は不要です。
全マッチの取得は『re.findall() / re.finditer()』を、置換・分割は『re.sub() / re.split() / re.compile()』を参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。