🐍 Python
名前付きグループ:(?P<name>...)
正規表現の丸括弧(...)は「グループ」として一致した部分を取り出せますが、複数のグループがあるとgroup(1)、group(2)のように番号で管理する必要があり、パターンが複雑になるほど「どの番号が何を表すか」が分かりにくくなります。(?P<name>...)という書き方でグループに名前を付けておくと、番号ではなく名前でアクセスできるようになり、AIが生成した正規表現を後から読むときにも意図がすぐ分かります。
構文: (?Pパターン)
アクセス方法: m.group('name') または m.groupdict()
基本の使い方:日付を年・月・日に分解する
それぞれのグループにyear、month、dayという名前を付けています。
import re
m = re.match(r'(?P\d{4})-(?P\d{2})-(?P\d{2})', '2026-08-09')
print(m.group('year')) # '2026'
print(m.group('month')) # '08'
print(m.group('day')) # '09'
groupdict()で辞書としてまとめて取り出す
名前付きグループを1つずつ.group()で呼ぶ代わりに、.groupdict()を使うと全部まとめて辞書として取得できます。設定ファイルのパース結果をそのまま辞書として扱いたいときに便利です。
import re
m = re.match(r'(?P\d{4})-(?P\d{2})-(?P\d{2})', '2026-08-09')
print(m.groupdict())
# {'year': '2026', 'month': '08', 'day': '09'}
名前を付けても番号でもアクセスできる
名前付きグループであっても、通し番号は消えません。.group(1)のような番号アクセスと、.groups()で全グループをタプルとしてまとめて取得する方法も併用できます。
import re
m = re.match(r'(?P\d{4})-(?P\d{2})-(?P\d{2})', '2026-08-09')
print(m.group(1), m.group(2), m.group(3)) # 2026 08 09(名前を付けても番号は生きている)
print(m.groups()) # ('2026', '08', '09')
省略可能なグループが一致しなかった場合
?を付けて「あってもなくてもよい」グループを作ることができますが、実際に一致しなかった場合、そのグループの値は空文字ではなくNoneになります。この違いを知らずに文字列として扱おうとすると、TypeErrorの原因になります。
import re
m = re.match(r'(\w+)(-(\w+))?', 'foo')
print(m.group(1)) # 'foo'
print(m.group(3)) # None(2つ目のグループは一致しなかったのでNone)
主なメソッド
- m.group(name または番号)
- 指定した名前・番号のグループの値を取得。
m.group()やm.group(0)は一致箇所全体 - m.groups()
- 番号付きグループすべてをタプルで取得(名前付きグループも含まれる)
- m.groupdict()
- 名前付きグループだけを辞書として取得
💡 Noneチェックを忘れない
省略可能なグループを含むパターンをAIが生成しているのを見たら、そのグループの値を使う箇所でNoneチェックが行われているかを必ず確認してください。「一致したグループの値を.upper()などの文字列メソッドにそのまま渡している」ようなコードは、そのグループが一致しなかった瞬間にAttributeErrorで落ちる典型的な事故パターンです。