Python の正規表現モジュール re には、パターンにマッチした部分を別の文字列に置き換える re.sub 関数がある。単純な str.replace では対応できない柔軟な置換処理を、この関数ひとつで実現できる。
基本的な使い方
re.sub の基本シグネチャは re.sub(pattern, repl, string, count=0, flags=0) だ。pattern にマッチした部分を repl で置き換え、結果の文字列を返す。元の文字列は変更されない。
import re
text = "Today is 2025-02-08"
result = re.sub(r"\d{4}-\d{2}-\d{2}", "YYYY-MM-DD", text)
print(result) # Today is YYYY-MM-DD
この例では日付パターンにマッチした部分がプレースホルダに置き換わる。str.replace と違い、特定の形式を持つ文字列だけを狙い撃ちできるのが強みだ。
count で置換回数を制限する
デフォルトではすべてのマッチが置換対象になるが、count を指定すると先頭から数えた回数分だけ置換される。
import re
text = "apple banana apple cherry apple"
result = re.sub(r"apple", "orange", text, count=2)
print(result) # orange banana orange cherry apple
3 つある apple のうち、先頭の 2 つだけが orange に変わっている。ログの先頭数行だけ加工したいときなどに便利な引数である。
関数を使った動的な置換
repl に文字列ではなく関数を渡すと、マッチオブジェクトを受け取って動的に置換文字列を生成できる。これが re.sub の真価を発揮する場面だ。
import re
text = "price: 100, tax: 8, total: 108"
def double(match):
return str(int(match.group()) * 2)
result = re.sub(r"\d+", double, text)
print(result) # price: 200, tax: 16, total: 216
マッチした数値を整数に変換し、2 倍にして返している。固定文字列では実現できない、文脈に応じた置換が可能になる。
グループを参照した置換
repl 文字列の中で \1 や \g<n> を使うと、パターン中のグループでキャプチャした部分を参照できる。
import re
text = "Tanaka Taro, Suzuki Hanako"
result = re.sub(r"(\w+) (\w+)", r"\2 \1", text)
print(result) # Taro Tanaka, Hanako Suzuki
\1 が姓、\2 が名にあたり、順序を入れ替えて「名 姓」の形式に変換している。CSV やログの整形でよく使われるテクニックだ。
re.subn で置換回数を取得する
置換した結果だけでなく「何回置換が行われたか」を知りたい場合は re.subn を使う。戻り値がタプルになり、置換後の文字列と置換回数の組が返される。
import re
text = "aaa bbb aaa ccc aaa"
result, n = re.subn(r"aaa", "xxx", text)
print(result) # xxx bbb xxx ccc xxx
print(n) # 3
バリデーション後に「何件修正したか」をログに残すような場面で活躍する。
str.replace と re.sub の使い分け
単純な文字列の置き換えには str.replace で十分であり、正規表現を持ち出す必要はない。re.sub が必要になるのは、パターンベースの柔軟なマッチングや、関数による動的置換が求められるケースだ。
固定文字列の置換に最適。高速で意図も明確になる。正規表現の知識が不要なので可読性も高い。
パターンマッチによる置換、グループ参照、関数置換など高度な処理が可能。ただし正規表現の理解が前提になるため、不要な場面で使うと可読性を下げる。
迷ったらまず str.replace で書けないか考え、無理なら re.sub に切り替える。この判断基準を持っておくと、コードの見通しがよくなる。