Pythonのreモジュールには、正規表現を使うための関数が複数用意されています。マッチした部分を取り出す関数、置換する関数、分割する関数、パターンを使い回すための関数など、目的ごとに使い分けます。
たとえば「文字列の中から数字だけを取り出す」なら、最初の1件だけでよいのか、全件ほしいのかで使う関数が変わります。最初の1件はre.search、全件をリストで取るならre.findall、1件ずつ位置情報も欲しいならre.finditer、という具合です。似た関数がいくつもあるので、それぞれの違いを整理します。
本記事では、reモジュールでよく使う関数を、Pythonのreモジュールで一つずつ整理します。reモジュールは標準モジュールなのでインストールは不要です。
なお、本記事で使う正規表現の基本構文・グループ・フラグは過去の記事で扱っています。
目次
関数の一覧
本記事で扱う関数を先に一覧で示します。用途で3つに分けています。
■ マッチした部分を取り出す(読み取り)
| 関数 | 戻り値 | 主な用途 |
|---|---|---|
re.search | 最初のMatch/None | どこかに一致する部分があるか探す |
re.match | 文字列先頭からのMatch/None | 文字列の先頭からパターンに一致するか調べる |
re.fullmatch | 文字列全体のMatch/None | 文字列全体がパターンに一致するか調べる |
re.findall | 一致した部分のリスト | 全ての一致する箇所を一気にリストで取る |
re.finditer | Matchのイテレータ | 全ての一致する箇所を、位置情報付きで1件ずつ処理 |
■ 置換・分割(書き換え)
| 関数 | 戻り値 | 主な用途 |
|---|---|---|
re.sub | 置換後の文字列 | 一致した部分を別の文字列に置き換える |
re.subn | (置換後の文字列, 置換回数) | 置換に加えてその回数も知りたい場合 |
re.split | 分割後の文字列のリスト | パターンにマッチする位置で文字列を分割する |
■ 補助
| 関数 | 戻り値 | 主な用途 |
|---|---|---|
re.compile | Patternオブジェクト | 同じパターンを何度も使うときに事前コンパイルする |
re.escape | エスケープ済みの文字列 | 記号を含む文字列をリテラルとしてマッチさせる |
re.search・re.match・re.fullmatchが返すMatchオブジェクトは、パターンに一致した部分を表すオブジェクトです。.group()で一致した文字列、.span()で位置(開始と終了のインデックス)、キャプチャグループがあれば.group(1)や.group("名前")で個別の値を取り出せます。グループの詳細はこちらの記事を参照ください。
なお、re.escapeを除くすべての関数は、オプションで末尾にflags引数を取ります。フラグ(re.Iなど)を、どの関数でも共通の形で渡せます。基本の呼び出し方はre.関数(パターン, 文字列, flags=re.I)です。フラグの詳細はこちらの記事を参照ください。
re.sub・re.subnはcount、re.splitはmaxsplitという別のオプション引数を持ちますが、flags=re.Iのようにキーワード引数で明示すれば、これらの関数でも同じ形で渡せます。
マッチした部分を取り出す
マッチした部分を読み取る関数を順に見ていきます。
最初の1件を探す(re.search)
re.searchは、文字列の中でパターンに一致する最初の部分を探し、見つかればMatchオブジェクト、なければNoneを返します。
m = re.search(r"\d+", "商品コード A123、在庫 45個")
print(m.group()) # '123'
print(m.span()) # (7, 10)
print(re.search(r"\d+", "no digits")) # None\d+(1個以上の数字)を先頭から探し、最初に見つかった123が返ります。Matchオブジェクトからは.group()で一致した文字列、.span()で位置が取れます(グループ編参照)。一致がなければNoneなので、if文で有無を判定できます。
先頭から一致するかを見る(re.match)
re.matchは、文字列の先頭からパターンに一致するかを見ます。先頭にあればMatchオブジェクト、そうでなければNoneです。
print(re.match(r"\d+", "123abc")) # <re.Match object; span=(0, 3), match='123'>
print(re.match(r"\d+", "abc123")) # None123abcは先頭が数字なので一致します。abc123は数字がありますが、先頭ではないのでNoneです。
なお、re.matchはre.MULTILINEを付けても各行の先頭は見ず、文字列の先頭でしか照合しません。
print(re.match(r"banana", "apple\nbanana", re.MULTILINE)) # None先頭から一致する必要がない場合は、re.searchの方が使いやすい場面が多くなります。
文字列全体が一致するかを見る(re.fullmatch)
re.fullmatchは、文字列全体がパターンに一致するかを見ます。一部だけ一致していてもNoneになります。
print(bool(re.fullmatch(r"\d+", "123"))) # True
print(bool(re.fullmatch(r"\d+", "123abc"))) # False"123"は全体が数字なので一致します。"123abc"は先頭は数字ですが末尾にabcが残るため一致しません。入力が「数字だけ」「メールアドレスの形式に完全に合う」といった形式全体の検証に使います。
全ての一致箇所をリストで受け取る(re.findall)
re.findallは、パターンに一致する全ての部分をリストで返します。戻り値の形は、パターンのキャプチャグループ数によって変わります。
print(re.findall(r"\d+", "a12 b345 c6")) # ['12', '345', '6']
print(re.findall(r"(\d+)", "a12 b345 c6")) # ['12', '345', '6']
print(re.findall(r"([a-z])(\d+)", "a12 b345")) # [('a', '12'), ('b', '345')]キャプチャグループがない場合はマッチ全体のリスト、1個ならそのグループの文字列のリスト、2個以上ならタプルのリストになります。
Matchを1件ずつ受け取る(re.finditer)
re.finditerは、パターンに一致する全ての部分を、Matchオブジェクトのイテレータとして返します。re.findallと違って、位置情報(.span())などMatchの情報を1件ずつ扱えます。
for m in re.finditer(r"\d+", "a12 b345"):
print(m.group(), m.span())
# 12 (1, 3)
# 345 (5, 8)一致した文字列だけでなく、どこにあるか・どのグループに何が入っているかも取り出したいときは、re.findallではなくre.finditerを使います。
置換・分割
書き換え行う関数を順に見ていきます。
置換する(re.sub)
re.subは、パターンに一致する部分を別の文字列に置き換えます。
print(re.sub(r"\d+", "#", "a12 b345")) # 'a# b#'
print(re.sub(r"\d+", "#", "a12 b345", count=1)) # 'a# b345'\d+にマッチする部分を#に置き換えます。count引数を指定すると、置換する回数を制限できます。
置換文字列の中では、キャプチャグループを参照できます。\1・\2のように番号で、名前付きグループなら\g<名前>で参照します(置換文字列もr"..."で書くのが安全です)。
print(re.sub(r"(\w+)@(\w+)", r"\2@\1", "user@example")) # 'example@user'
print(re.sub(r"(?P<y>\d{4})-(?P<m>\d{2})", r"\g<m>/\g<y>", "2026-07")) # '07/2026'1つ目は、@の左右を入れ替えています。2つ目は、2026-07(年-月)を07/2026(月/年)に並べ替えています。\g<0>と書くとマッチ全体を参照できます。
置換の内容を動的に決めたいときは、置換文字列の代わりに関数を渡せます。関数はMatchを受け取り、置換後の文字列を返します。
print(re.sub(r"\d+", lambda m: str(int(m.group()) * 2), "a12 b345")) # 'a24 b690'一致した数字を2倍にしています。数字ごとに違う値へ置き換えたいときに便利です。
置換に加えて回数を返す(re.subn)
re.subnは、re.subと同じ置換をしたうえで、(置換後の文字列, 置換回数)のタプルを返します。置換した回数も同時に知りたい場面で使います。
print(re.subn(r"\d+", "#", "a12 b345")) # ('a# b#', 2)置換した文字列と、置換した回数(2)が返ります。
パターンで分割する(re.split)
re.splitは、パターンに一致する位置で文字列を分割し、リストで返します。str.splitより柔軟な区切り方ができます。
print(re.split(r"\s+", "a b c")) # ['a', 'b', 'c']\s+(1個以上の空白)で分割し、空白の連続数に関係なく3要素になります。
パターンにキャプチャグループを入れると、区切りに使った部分も結果に含まれます。
print(re.split(r"(\s+)", "a b")) # ['a', ' ', 'b']分割されたa・bに加えて、区切り自体の' '(空白2個)もリストに入ります。区切り文字も残したいときに使います。
maxsplit引数で、分割回数の上限を指定できます。
print(re.split(r"\s+", "a b c d", maxsplit=1)) # ['a', 'b c d']1回だけ分割するので、先頭のaと残り全体b c dの2要素になります。
補助
正規表現のパターンをオブジェクトとして定義するなど、補助の役割をする関数を順に見ていきます。
パターンの定義
re.compileは、パターンをあらかじめコンパイルして、Patternオブジェクトとして返します。同じパターンを何度も使う場面で、毎回パターンを解釈し直す手間を省けます。
pattern = re.compile(r"\d+")
print(pattern.findall("a12 b345")) # ['12', '345']
print(pattern.search("a12").group()) # '12'Patternオブジェクトには、reモジュールの関数と同名のメソッド(search・match・findall・subなど)があり、パターンを引数に取らない点だけが違います。ループの中で何度も同じパターンを使うときや、パターンを1か所にまとめて管理したいときに使います。
記号を含む文字列をリテラルにマッチさせる
re.escapeは、文字列中の正規表現メタ文字(.・*・(・)・?など)にバックスラッシュを付けて、そのままの文字としてマッチできる形に変換します。
s = "1.2.3"
print(re.escape(s)) # '1\\.2\\.3'
print(bool(re.search(s, "1x2y3"))) # True .が任意文字と解釈されて誤マッチ
print(bool(re.search(re.escape(s), "1x2y3"))) # False
print(bool(re.search(re.escape(s), "value: 1.2.3"))) # True"1.2.3"をそのままパターンとして使うと、.が「任意の1文字」と解釈されるため、"1x2y3"にも一致してしまいます。re.escapeを通すと.が\.になり、リテラルの.だけにマッチするようになります。ユーザー入力や変数など、メタ文字が含まれるかもしれない文字列をパターンに組み込むときに使います。
まとめ
reモジュールの主な関数を、用途別に整理しました。
一致の有無や位置だけ知りたいならsearch/match/fullmatch、全件を取るならfindall/finditer、書き換えならsub/subn/split、と目的で選ぶと迷いにくくなります。