正規表現 - グループ化と参照

正規表現において、グループ化(Grouping)は、数学における括弧のように、複数の文字を1つのまとまりとして扱うことを可能にします。グループ化には主に2つの役割があります:

  1. 複数の文字を1つのまとまりとして扱う:このまとまりに対して量指定子を適用できます(例:*、+、?、{n})
  2. マッチした内容をキャプチャする:後でこのマッチした部分を参照または抽出できます

基本構文

丸括弧を使用して()グループを作成します:

(式)

例えば、(ab)+は "ab"、"abab"、"ababab" などにマッチできますが、"a" や "b" にはマッチできません。


グループの種類

正規表現にはいくつかの異なるタイプのグループがあります:

1. キャプチャグループ(Capturing Group)

最も一般的なグループ形式で、マッチした内容をキャプチャし、番号(1から始まる)を割り当てます。

例

(\d{4})-(\d{2})-(\d{2})# 日付形式 YYYY にマッチ-MM-DD

この式は3つのグループを作成します:

  • グループ1:4桁の年
  • グループ2:2桁の月
  • グループ3:2桁の日

2. 非キャプチャグループ(Non-capturing Group)

使用する(?:式)構文は、グループ化のみ行いキャプチャしないことを示します。

例

(?:Mr|Ms|Mrs)\. (\w+)# マッチ"Mr. Smith"ただしキャプチャするのは"Smith"

3. 名前付きキャプチャグループ(Named Capturing Group)

グループに名前を指定して可読性を高めます(言語によって構文が異なる場合があります)。

Python の例:

例

(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})

JavaScript の例:

例

(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})

グループ参照

グループの最も強力な機能の1つは、正規表現の内部または外部でマッチした内容を参照できることです。

1. 後方参照(Backreference)

正規表現内で前方のグループを参照するには、\数字構文を使用します:

例

(\w+) \1# 繰り返される単語にマッチ、例:"hello hello"

このパターンは、スペースで区切られた2つの同一単語にマッチします。

2. 名前付き後方参照

名前付きグループの場合、名前を使用して参照できます:

例

(?P<word>\w+) (?P=word)# Python 構文
\k<word># JavaScript 構文

3. 置換参照

置換操作でグループの内容を参照します:

Python の例:

例

import re
text = "2023-05-15"
new_text = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\2/\3/\1', text)
# 結果: "05/15/2023"

JavaScript の例:

例

let text = "2023-05-15";
let newText = text.replace(/(\d{4})-(\d{2})-(\d{2})/, '$2/$3/$1');
// 結果: "05/15/2023"

実践的な使用例

例1:HTMLタグのマッチング

例

<([a-z][a-z0-9]*)\b[^>]*>.*?</\1>

このパターンは対になったHTMLタグ(例:<div>...</div>)にマッチできます。ここで:

  • ([a-z][a-z0-9]*)タグ名をキャプチャする
  • \1前にキャプチャしたタグ名を参照して、前後が一致することを保証する

例2:繰り返し単語の検証

例

\b(\w+)\b\s+\1\b

テキスト内で連続して繰り返される単語を見つけ出せます。

例3:日付形式の変換

Python コード:

例

import re

date = "2023-12-25"
# YYYY-MM-DD を DD/MM/YYYY に変換
new_date = re.sub(r'(\d{4})-(\d{2})-(\d{2})', r'\3/\2/\1', date)
print(new_date)  # 出力: 25/12/2023

グループの高度な応用

1. 条件付きマッチング

一部の正規表現エンジンは、グループに基づく条件付きマッチングをサポートしています:

例

(?(1)true-pattern|false-pattern)

グループ1がマッチした場合は true-pattern にマッチし、そうでない場合は false-pattern にマッチすることを示します。

2. バランスグループ(高度な機能)

ネスト構造(括弧など)のマッチングに使用され、特定の正規表現エンジンのサポートが必要です。


よくある問題と落とし穴

  1. グループの過度な使用:不要なグループはパフォーマンスに影響を与えます

    • 悪い例:(a)|(b)(キャプチャが不要な場合は、(?:a|b))
  2. グループ番号の混乱:

    • グループ番号は左括弧の順に1から始まります
    • 非キャプチャグループは番号付けに含まれません
  3. 貪欲マッチングの問題:

    <(.*)>  # 最後の > まで貪欲にマッチする

    次を使用すべきです:

    <(.*?)>  # 非貪欲マッチ

練習問題

  1. 繰り返される電子メールのユーザー名にマッチする正規表現を書いてください(例:[email protected];[email protected])
  2. 電話番号形式を変換する、から(123) 456-7890 到 123-456-7890
  3. HTMLタグ内のすべての属性を抽出する(例:<img src="..." alt="...">内の src と alt)

要点まとめ

概念 構文 用途
キャプチャグループ (pattern) マッチした内容をキャプチャし番号を割り当てる
非キャプチャグループ (?:pattern) グループ化するがキャプチャしない
名前付きキャプチャグループ (?P<name>pattern) (Python) グループに名前を指定する
後方参照 \1, \2 等 前にマッチしたグループを参照する
名前付き後方参照 (?P=name) (Python) 名前でグループを参照する
置換参照 $1, $2 或 \1, \2 置換文字列内でグループを参照する

正規表現のグループ化と参照機能を習得すると、以下のことが可能になります:

  • より複雑なマッチングパターンを構築する
  • 文字列内の特定の部分を抽出および処理する
  • 文字列のスマートな変換を実装する
  • 複雑なテキスト構造を検証する
その他の拡張