🐍 Python
re.compile(pattern, flags=0)
re.matchやre.findallを毎回呼び出すと、Pythonは内部でそのつどパターンを解釈し直しています。同じパターンをループの中で何度も使う場合、re.compileで事前にコンパイルしておくと、それ以降は同じ解析済みパターンを使い回せます。「同じ正規表現を繰り返し使うときの定石」として覚えておく価値があります。
構文: re.compile(pattern, flags=0)
戻り値: コンパイル済みのPatternオブジェクト
基本の使い方:コンパイルしてから何度も使う
コンパイル済みのオブジェクトは、re.findall(pattern, string)のような形ではなく、オブジェクト自身に対して.findall(string)のようにメソッドとして呼び出します。
import re
pattern = re.compile(r'\d+')
print(pattern.findall('a1b22')) # ['1', '22']
print(pattern.match('99abc').group()) # '99'
コンパイル時にフラグを指定する
フラグは呼び出しのたびに指定する代わりに、コンパイル時に一度だけ指定しておくこともできます。以降そのオブジェクトを使うたびに毎回同じフラグが適用されます。
import re
pattern = re.compile(r'error', re.IGNORECASE)
print(pattern.search('Critical ERROR occurred').group()) # 'ERROR'
ループの中で同じパターンを繰り返し使う例
複数行のログを1行ずつ処理するような場面で、パターンを1回だけコンパイルしておくと効率的です。
import re
log_lines = ['user=alice id=1', 'user=bob id=2', 'user=carol id=3']
pattern = re.compile(r'user=(\w+)')
for line in log_lines:
m = pattern.search(line)
print(m.group(1))
# alice
# bob
# carol
コンパイル済みオブジェクトの主なメソッド
- pattern.match(string) / .search(string) / .fullmatch(string)
- re.match等と同じ動作。第一引数のパターンが省略された形で呼び出せる
- pattern.findall(string) / .finditer(string)
- re.findall等と同じ動作
- pattern.sub(repl, string) / .split(string)
- re.sub・re.splitと同じ動作
💡 毎回re.compileし直しては意味がない
ループの中で毎回re.compileを呼んでいるコードは、コンパイルのメリットを活かせていません。AIが生成したコードでこのパターンを見かけたら、コンパイルをループの外に出せないかを確認してください。1回だけ実行される処理であれば、素直にre.findallのような関数を直接呼ぶ書き方のほうがシンプルで、無理にcompileを使う必要はありません。