Menu

Python 正規表現入門 | reモジュールの使い方を解説

Pythonのreモジュールを使った正規表現の基本を実例で解説。search・match・findall・subからグループ化、置換までひと通り押さえます。

このページのコードはエディタで実行できます — 編集してすぐに結果を確認できます。

正規表現を使うべき場面

Python の正規表現は、テキストのパターンを記述するための小さな専用言語のようなものです。強力ですが、つい使いすぎてしまいがちな機能でもあります。

re モジュールに手を伸ばす前に、まずは普通の文字列メソッドで十分じゃないか考えてみましょう。.split().replace().startswith()"target" in text といったものは、同じことを正規表現でやるよりも速く、読みやすく、バグも入りにくいです。正規表現の出番は、探したいパターンが ある程度の構造を持ちつつも 固定の文字列操作では対応しきれないくらい柔軟なとき。たとえばメールアドレス、電話番号、形式の決まったログ行、HTML や Markdown の断片など、「この手のやつを見つけたい」という検索です。

基本の記法

正規表現の パターン は、「何を探しているか」を表す文字列です。よく使うパーツを並べてみます。

  • . — 任意の 1 文字
  • \d — 数字 1 文字(0〜9)
  • \w — 「単語」を構成する文字(英字・数字・アンダースコア)
  • \s — 空白文字
  • ^ — 文字列の先頭
  • $ — 文字列の末尾
  • [abc] — a、b、c のいずれか 1 文字
  • [^abc] — a、b、c 以外の任意の 1 文字
  • a|b — a または b
  • * — 直前の要素の 0 回以上の繰り返し
  • + — 1 回以上の繰り返し
  • ? — 0 回または 1 回
  • {3} — ちょうど 3 回
  • {2,5} — 2 回以上 5 回以下
  • ( ... ) — グループ化(中身をキャプチャする)

実務で使う正規表現のほとんどは、これだけで書けてしまいます。

主な関数

re.search の使い方

re.search(pattern, text) は、文字列のどこかに最初に現れるマッチを探します。マッチオブジェクトか、見つからなければ None を返します。

正規表現のパターンには必ず raw 文字列(r"...")を使いましょう。そうしないと、Python がバックスラッシュを文字列エスケープとして解釈してしまい、書いたつもりのパターンとは別物になってしまいます。

re.match(pattern, text)search と似ていますが、文字列の先頭でのみマッチを試みます。

ほとんどの場合は search を使えば事足ります。

re.findall(pattern, text) は、重ならないマッチをすべてリストで返してくれます。

findall が返すのは文字列であって、マッチオブジェクトではない点に注意してください。パターンにグループが1つだけ含まれる場合はそのグループの中身が返り、複数のグループがある場合はタプルのリストになります。

グループ化によるキャプチャ

パターン内の丸括弧 () は、その中にマッチした部分をキャプチャします。

名前付きグループ を使うと、コードがぐっと読みやすくなります。

グループが2つ以上になると、名前を付けておいた方が抽出するコードがぐっと読みやすくなります。

re.sub で置換する

re.sub(pattern, replacement, text) は、マッチした部分をすべて置き換えます。

これで数字以外をすべて取り除けます。置換側ではキャプチャしたグループを \1\2 のように参照できます。raw 文字列を使う場合は \g<1> と書いた方が分かりやすいでしょう。

置換部分には関数を渡すこともできます。単純な置き換えでは表現できない変換をしたいときに便利です。

パターンをコンパイルして使い回す

同じパターンを何度も使う場合、特にループの中で繰り返し使うようなときは、一度コンパイルしておくのがおすすめです。

コンパイル済みのパターンでも、searchmatchfindallsub といった同じメソッドが使えます。ただし第一引数にパターンを渡す必要はありません。少しだけ高速で、コードも読みやすくなることが多いです。

フラグ

よく使う修飾子は、flags= 引数で渡すか、| で組み合わせて指定します。

  • re.IGNORECASE (re.I) — 大文字・小文字を区別せずにマッチします。
  • re.MULTILINE (re.M) — ^$ が文字列全体の先頭・末尾だけでなく、各行の先頭・末尾にもマッチするようになります。
  • re.DOTALL (re.S) — . が改行にもマッチするようになります(デフォルトではマッチしません)。
  • re.VERBOSE (re.X) — パターン内に空白や # によるコメントを書けるようになり、可読性が向上します。

re.VERBOSE は複雑なパターンを書くときに特に便利です。

複数行でコメントを添えた正規表現は、意味不明な一行パターンに比べてメンテナンスが圧倒的にラクになります。

貪欲マッチと最小マッチ

量指定子(*+?{n,})は、デフォルトでは 貪欲(greedy) に動作し、マッチできる範囲を可能な限り長く取ろうとします。末尾に ? を付けると 最小マッチ(lazy) に切り替わります。

貪欲マッチの方は <b> から </i> までまるごと拾ってしまっていて、たぶん欲しかった結果とは違いますよね。最小マッチの .+? なら最初の > の時点で止まってくれます。

(余談ですが、本番で HTML を正規表現でパースするのはやめましょう。html.parser か BeautifulSoup を使ってください。上の例はあくまで貪欲マッチの挙動を示すためのものです。)

実践的なサンプル

シンプルなログ形式の行をパースしてみます。

たった数行でこれだけのことができてしまいます。

ちょっとしたコツ

  • パターンは必ず raw 文字列(r"...")で書く。
  • まずは動く最小のパターンから始め、あとから絞り込む。
  • グループが2つ以上になったら名前付きグループを使う。
  • 繰り返し使うパターンは compile しておく。
  • 正規表現は普通の文字列メソッドより遅い。.split() で足りるなら .split() を使う。

次は: エラーとデバッグ

これで実データを扱うひと通りのツアー(ファイル、JSON、CSV、HTTP、日付、そして正規表現)は終わりです。とはいえ、実際のプログラムを書けば遅かれ早かれエラーに遭遇します。そして Python のトレースバックをきちんと読めるようになることは、デバッグ力を伸ばすうえで何よりも効きます。最終章では例外処理と、現場でよく出会う代表的なエラーについて見ていきます。

よくある質問

Pythonにおける正規表現とは?

正規表現(regex)は、文字列のパターンを記述するための小さな言語です。Pythonでは標準ライブラリの re モジュールを使って、パターン検索・抽出・置換ができます。ただし、単純な文字列操作なら .split().replace() などの文字列メソッドで十分。正規表現はあくまで、構造のあるパターンをマッチさせたいときの切り札として使うのがおすすめです。

re.match と re.search の違いは?

re.match は文字列の先頭からしかマッチを試みません。一方 re.search は文字列全体を走査して、どこかにマッチがあれば最初の一件を返します。迷ったときは search を使うのが無難です。多くの人が直感的に期待する挙動はこちらのほうです。

正規表現のパターンは raw 文字列(r"...")で書くべき?

はい、基本的に raw 文字列で書くのがおすすめです。正規表現には \d\s\b のようにバックスラッシュを含む記号が頻出しますが、通常の文字列だとPythonがエスケープシーケンスとして解釈してしまいます。r'\d+' のように r を付けておけば文字列がそのまま扱われるので、パターンが読みやすくなりバグも減ります。

Coddy programming languages illustration

Coddyでコードを学ぼう

始める