正規表現(re モジュール)はテキスト処理で超便利ですが、最初は記号の意味に慣れることが肝心です。ここでは 初心者が最短で使えるように、概念→主要パターン→re の使い方→実例→練習問題(解答付き)まで、やさしくまとめます。コードはそのまま Python で動きます。
1. 正規表現って何?
正規表現(regex)は「文字列パターンを表す式」です。メールや電話番号の抽出、ログ解析、置換などで使います。短くて強力ですが、最初は少し記号を覚えるだけでかなり使えるようになります。
2. 基本の考え方(重要)
- 正規表現は「検索したい文字列のルール」を書いたもの。
- Python では
import reして、re.search()/re.match()/re.findall()/re.sub()などを使います。 - パターンは 生文字列(raw string)で書くのがおすすめ:
r"..."。バックスラッシュの扱いが楽になります。
import re
pat = r"\d+" # 数字が1回以上
re.findall(pat, "abc123def45") # -> ['123','45']
Python3. よく使う記号(覚え方メモ)
文字系
.:任意の1文字(改行は除く、フラグで変える)\d:数字(0-9) — 同義[0-9]\D:数字以外(\dの否定)\w:単語構成文字(英数字+アンダースコア) — 同義[A-Za-z0-9_]\W:\w以外\s:空白(スペース、タブ、改行など)\S:空白以外
量指定(回数)
a*:0 回以上(可能な限り多く)a+:1 回以上(最もよく使う)a?:0 回または 1 回(あるかも)a{m}:ちょうど m 回a{m,n}:m〜n 回(範囲)
位置とグループ
^:行頭(例:^Hello)$:行末(例:end$)():グループ化・キャプチャ(後で参照)(?: ):グループ化するがキャプチャしない(性能向上や後方参照不要時に便利)|:または(OR)
例(分かりやすさ重視)
^\d{4}-\d{2}-\d{2}$→YYYY-MM-DD形式にマッチ(行全体が日付と一致)\bword\b→ 単語単位でwordにマッチ(単語境界\b)
4. Python の re でよく使う関数
import re
re.search(pattern, text) # パターンが anywhere にあるか。Matchオブジェクト or None
re.match(pattern, text) # 文字列先頭からマッチするか(search と違う)
re.findall(pattern, text) # マッチする全ての部分文字列をリストで返す
re.finditer(pattern, text) # マッチのイテレータ(Matchオブジェクトを順に)
re.sub(pattern, repl, text) # 置換(repl は文字列か関数)
re.split(pattern, text) # パターンで分割してリストを返す
re.compile(pattern, flags) # パターンをコンパイル(同じパターンを複数回使うなら有利)
PythonMatch オブジェクトからは .group() .groups() .start() .end() が使えます。
5. フラグ(オプション)
re.I/re.IGNORECASE:大文字小文字を区別しないre.M/re.MULTILINE:^と$が行単位になるre.S/re.DOTALL:.が改行にもマッチする
例:re.search(pattern, text, re.I | re.M)
6. 実用的な例(そのままコピペして試せます)
例 A — 数字列を全部取り出す
import re
text = "商品A: 123円, 商品B: 45円, #ID: 007"
nums = re.findall(r"\d+", text)
print(nums) # ['123','45','007']
Python例 B — Eメールっぽいものを抽出(単純版)
text = "連絡は taro@example.com または hanako@sample.co.jp へ"
emails = re.findall(r"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}", text)
print(emails)
Python※ 厳密な RFC 準拠ではありませんが、実務的には十分な場合が多いです。
例 C — 電話番号(日本の簡易パターン:例 03-1234-5678 や 090-1234-5678)
text = "連絡先: 03-1234-5678, 携帯: 090-9876-5432"
phones = re.findall(r"\b0\d{1,4}-\d{1,4}-\d{4}\b", text)
print(phones)
Python例 D — 置換(複数スペースを1つのスペースに)
s = "これは スペースが 多い 文です"
s2 = re.sub(r"\s+", " ", s).strip()
print(s2) # "これは スペースが 多い 文です"
Python例 E — グループを使って抽出(年月日のパーツ)
m = re.search(r"(\d{4})-(\d{2})-(\d{2})", "今日は2025-11-05です")
if m:
year, month, day = m.groups()
print(year, month, day) # '2025' '11' '05'
Python7. よくある「間違い」と対処法
- バックスラッシュを忘れる →
"\d"と書くと Python 側で解釈されることがある。r"\d"を使おう。 re.match()は「先頭」からしか見ない → 文字列内どこでも探したいときはre.search()を使う。- 貪欲(greedy)と非貪欲(lazy):
.*はできるだけ長くマッチする。最小マッチにしたいときは.*?を使う。
例:"<.+>"は<a> <b>で<a> <b>全体にマッチするが、"<.+?>"は最短の<a>と<b>に分かれる。 - 日本語や Unicode を扱うときも
\wなどは英数字中心なので注意。必要なら文字クラス[\u3040-\u30FF\u4E00-\u9FFF]のように指定する(やや上級)。
8. 練習問題 — 解答付き
問1:文字列 "abc123xyz456" から数字だけを取り出してリストにしなさい。
解答:
import re
s = "abc123xyz456"
re.findall(r"\d+", s) # -> ['123', '456']
Python問2:"price: .5, tax: .25" から小数も含めた金額を抜き出す正規表現を書きなさい。
解答:
import re
s = "price: $12.5, tax: $1.25"
re.findall(r"\$\d+(?:\.\d+)?", s) # -> ['$12.5', '$1.25']
Python問3:行頭に # がある行をコメント行として省いたリストを作りたい(テキストは改行で複数行)。どうする?
解答:
import re
text = "line1\n# comment\nline2\n#x\nline3"
lines = text.splitlines()
non_comments = [ln for ln in lines if not re.match(r"^\s*#", ln)]
# -> ['line1','line2','line3']
Python問4(少し応用):HTML の簡単なタグ <tag>...</tag> の中身だけ取り出す。ただしネストや属性は無視してOK。
解答:
import re
html = "<p>Hello</p><div>World</div>"
re.findall(r"<([a-zA-Z][a-zA-Z0-9]*)>(.*?)</\1>", html)
# -> [('p','Hello'), ('div','World')]
# グループ1はタグ名、グループ2は中身
Python9. まとめ(実務での使い分け)
- 単純な文字列検索や分割→
split,str.replace,inで十分。 - パターンが複雑(形式チェック、抽出、複数条件)→ 正規表現が強力。
- 大きなテキストや頻繁に同じパターンを使うなら
re.compile()でパターンをコンパイルして使うと速くてコードが読みやすい。
