目次

正規表現(Regular Expression、regex)は文字列のパターンを記述するための書式だ。ログファイルから特定のエラーを抽出する、LLMの出力からJSON部分だけを取り出す、メールアドレスの形式を検証するといった場面で、正規表現は数行のコードで強力な処理を実現する。

基本構文

メタ文字

正規表現では通常の文字に加えて、特殊な意味を持つ「メタ文字」を使う。

メタ文字意味
.任意の1文字(改行を除く)
^行の先頭
$行の末尾
\d数字([0-9]と等価)
\w単語文字([a-zA-Z0-9_]と等価)
\s空白文字(スペース・タブ・改行)

量指定子

量指定子意味
*0回以上
+1回以上
?0回または1回
{n}ちょうどn回
{n,m}n回以上m回以下

.*.+ の違いは「0回以上」と「1回以上」だ。.* は空文字列にもマッチするが .+ は1文字以上が必須だ。

文字クラス

[aeiou] は a, e, i, o, u のいずれか1文字にマッチする。[^aeiou] は先頭の ^ が否定を意味し、母音以外の文字にマッチする。[a-z] は a から z の範囲を表す。

グループとキャプチャ

() で囲んだ部分はグループを形成し、キャプチャグループとして後から参照できる。

import re
text = "Error: 404 Not Found"
match = re.search(r"Error: (\d+) (.+)", text)
if match:
    code = match.group(1)   # "404"
    msg = match.group(2)    # "Not Found"

(?:...) は非キャプチャグループで、グループ化はするが後から参照しない場合に使う。

貪欲マッチと非貪欲マッチ

デフォルトの量指定子は「貪欲(greedy)」で、できるだけ多くの文字にマッチしようとする。

text = "<b>太字</b>と<i>斜体</i>"
re.search(r"<.+>", text).group()  # "<b>太字</b>と<i>斜体</i>" — 全体にマッチ
re.search(r"<.+?>", text).group() # "<b>" — 最短マッチ(?を付けると非貪欲)

HTMLやXMLを正規表現でパースすることは一般的に非推奨だが、タグを含む文字列を扱う場合に ? による非貪欲マッチが重要になる。

LLM出力の後処理での実用例

LLMはJSON出力を要求してもマークダウンコードブロックで囲んで返すことがある。正規表現でJSON部分だけを抽出できる。

def extract_json(llm_output: str) -> str:
    # ```json ... ``` または ``` ... ``` のパターンに対応
    pattern = r"```(?:json)?\s*([\s\S]+?)\s*```"
    match = re.search(pattern, llm_output)
    if match:
        return match.group(1)
    # コードブロックがなければ { } の部分を探す
    match = re.search(r"\{[\s\S]+\}", llm_output)
    return match.group(0) if match else llm_output

先読み(Lookahead)と後読み(Lookbehind)

先読みは「マッチするが消費しない」特殊なグループだ。

# 正の先読み: 「円」の前の数字にマッチ
re.findall(r"\d+(?=円)", "1000円と500円")  # ['1000', '500']

# 正の後読み: 「¥」の後の数字にマッチ
re.findall(r"(?<=¥)\d+", "¥1000と¥500")   # ['1000', '500']

Pythonでの主なre関数

関数用途
re.match()文字列の先頭からマッチ
re.search()文字列全体から最初のマッチを検索
re.findall()すべてのマッチを文字列リストで返す
re.sub()マッチした部分を置換
re.compile()パターンをコンパイルして再利用(高速化)

頻繁に使うパターンは re.compile() でコンパイルしておくと、繰り返し適用する際のパフォーマンスが向上する。


まとめ

正規表現は習得コストが高く見えるが、基本のメタ文字と量指定子、グループを理解すれば実務の大半のケースに対応できる。.*.+ の差(0回以上か1回以上か)、貪欲マッチと非貪欲マッチ(**?)の区別は特に重要だ。LLM出力の後処理やログ解析では、正規表現による文字列抽出が日常的に必要となる。Python の re モジュールと re.compile() によるパターンの再利用を覚えておくと即戦力として使える。

免責事項 — 掲載情報は執筆時点のものです。料金・機能は変更される場合があります。最新情報は各公式サイトをご確認ください。