🐍 Python
re.finditer(pattern, string, flags=0)
re.findallと似た働きをしますが、一致した文字列だけを返すのではなく、一致箇所ごとにMatchオブジェクトをイテレータとして返します。Matchオブジェクトには一致した文字列に加えて出現位置(start()やspan())などの情報も含まれているため、「どこで見つかったか」まで知りたい場合に使います。
構文: re.finditer(pattern, string, flags=0)
戻り値: Matchオブジェクトを1件ずつ返すイテレータ
基本の使い方:一致箇所と位置を同時に取得する
for文で1件ずつ取り出し、.group()で文字列を、.span()で開始・終了位置のタプルを取得できます。
import re
for m in re.finditer(r'\d+', 'a1b22c333'):
print(m.group(), m.span())
# 1 (1, 2)
# 22 (3, 5)
# 333 (6, 9)
startだけ・endだけを個別に取る
span()はタプルでまとめて返しますが、開始位置だけ、終了位置だけをそれぞれstart()・end()で個別に取得することもできます。
import re
for m in re.finditer(r'\d+', 'a1b22c333'):
print(m.group(), '開始位置:', m.start())
# 1 開始位置: 1
# 22 開始位置: 3
# 333 開始位置: 6
名前付きグループと組み合わせる
名前付きグループと組み合わせると、複数のキー・値ペアを1件ずつ処理できます。設定ファイルやログの各行を順番に処理するような場面で便利です。
import re
for m in re.finditer(r'(?P\w+)=(?P\d+)', 'x=1 y=22'):
print(m.group('key'), m.group('val'))
# x 1
# y 22
パラメータ
- pattern
- 検索する正規表現パターン(文字列)。raw文字列
r'...'で書くのが基本 - string
- 検索対象の文字列
- flags(省略可)
- 動作オプション。詳しくはflagsのページを参照
💡 findallとどちらを使うべきか
単純に「一致した値の一覧が欲しいだけ」ならre.findallのほうがコードは短くなります。一方、位置情報が必要だったり、一致件数が非常に多くて一度に全部リスト化するとメモリを圧迫する場合は、1件ずつ処理できるre.finditerのほうが適しています。大きなログファイルを1行ずつ処理するようなAI生成コードでfinditerが使われていたら、それは意図的にメモリ効率を考えた書き方だと読み取れます。