この記事では、Pythonの正規表現モジュールre
が提供するfindall()
メソッドについて解説します。search()
メソッドが最初に見つかった一つのマッチオブジェクトを返すのに対し、findall()
は文字列内にあるパターンに一致するすべての部分文字列をリストとして返します。
search()
メソッドとの違い
まず、search()
メソッドの動作を思い出してみましょう。search()
は、パターンに一致する最初の箇所を見つけると、そこで検索を終了し、一つのマッチオブジェクトを返します。
import re
text = "連絡先A: 090-1234-5678, 連絡先B: 080-9999-8888"
phone_pattern = re.compile(r'\d{3}-\d{4}-\d{4}')
match_object = phone_pattern.search(text)
print(match_object.group()) # 出力: 090-1234-5678
テキスト内に電話番号が二つあっても、search()
は最初のものしか見つけません。
findall()
メソッドの基本動作
一方、findall()
メソッドは、文字列全体を検索し、パターンに一致するすべての部分文字列をリストにして返します。
import re
text = "連絡先A: 090-1234-5678, 連絡先B: 080-9999-8888"
phone_pattern = re.compile(r'\d{3}-\d{4}-\d{4}')
all_matches = phone_pattern.findall(text)
print(all_matches) # 出力: ['090-1234-5678', '080-9999-8888']
これにより、テキストに含まれるすべての電話番号を一度に抽出できます。
グループがある場合のfindall()
の動作
正規表現パターンに丸括弧()
によるグルーピングが含まれている場合、findall()
の動作が変わるため注意が必要です。
パターンにグループが含まれていると、findall()
はマッチした文字列全体ではなく、グループにマッチした部分文字列のタプルをリストにして返します。
import re
text = "連絡先A: 090-1234-5678, 連絡先B: 080-9999-8888"
# パターンをグループ化: (市外局番)-(中間)-(加入者番号)
phone_pattern_grouped = re.compile(r'(\d{3})-(\d{4})-(\d{4})')
all_grouped_matches = phone_pattern_grouped.findall(text)
print(all_grouped_matches)
実行結果:
[('090', '1234', '5678'), ('080', '9999', '8888')]
返り値が、マッチした文字列全体のリストではなく、各マッチのグループ部分を格納したタプルのリストになっていることがわかります。これは、電話番号の各部分を個別に抽出したい場合に非常に便利です。
まとめ
findall()
メソッドは、テキストから特定のパターンに一致する箇所をすべて抽出するための強力なツールです。正規表現パターンにグループが含まれていない場合は、マッチした文字列全体のリストを返します。パターンにグループが含まれている場合は、各グループにマッチした文字列からなるタプルのリストを返します。この動作の違いを理解することで、テキストデータから必要な情報をより柔軟に抽出できるようになります。