Open1

pythonのライブラリ「re」を使用して正規表現を使いこなそう

ひでひで

タイトルにもある通りpythonのライブラリ「re」を使用して正規表現をマスターしていきましょう!!
正規表現を使用すると特定の文字列や数値などの抽出が容易で正確になります。
コードも簡潔に済みます。
業務自動化ツールの作成やデータクリーニング、データ抽出などの場面でとても役に立ちます。

📦 reモジュールの主要メソッド

1. re.findall() - 全部見つける

import re

text = "私の電話番号は090-1234-5678で、友達は080-9999-8888です"

# 数字を全部見つける
numbers = re.findall(r'\d', text)
print("数字:", numbers)  # ['0', '9', '0', '1', '2', '3', '4', ...]

# 電話番号を全部見つける
phones = re.findall(r'\d{3}-\d{4}-\d{4}', text)
print("電話番号:", phones)  # ['090-1234-5678', '080-9999-8888']

2. re.search() - 最初の1個だけ見つける

text = "今日は2025年7月10日です。明日は2025年7月11日です。"

# 最初の日付だけ見つける
result = re.search(r'\d{4}年\d{1,2}月\d{1,2}日', text)
if result:
    print("見つけた:", result.group())  # 見つけた: 2025年7月10日
    print("位置:", result.start(), "から", result.end())  # 位置: 2 から 12
else:
    print("見つからない")

3. re.match() - 文字列の最初からチェック

text1 = "こんにちは世界"
text2 = "Hello World"

# 文字列の最初が「こんにちは」で始まるかチェック
result1 = re.match(r'こんにちは', text1)
result2 = re.match(r'こんにちは', text2)

print("text1の結果:", result1.group() if result1 else "マッチしない")  # こんにちは
print("text2の結果:", result2.group() if result2 else "マッチしない")  # マッチしない

4. re.sub() - 置き換える

text = "今日の気温は25度です。明日は30度の予定です。"

# 数字を「XX」に置き換える
result1 = re.sub(r'\d+', 'XX', text)
print("置き換え1:", result1)  # 今日の気温はXX度です。明日はXX度の予定です。

# 数字を「(数字)」に置き換える(グループ使用)
result2 = re.sub(r'(\d+)', r'(\1)', text)
print("置き換え2:", result2)  # 今日の気温は(25)度です。明日は(30)度の予定です。

5. re.split() - 分割する

text = "りんご,みかん;バナナ:いちご"

# いろんな記号で分割
result = re.split(r'[,;:]', text)
print("分割結果:", result)  # ['りんご', 'みかん', 'バナナ', 'いちご']

# 空白で分割(連続する空白は1つとして扱う)
text2 = "あ   い  う え    お"
result2 = re.split(r'\s+', text2)
print("空白分割:", result2)  # ['あ', 'い', 'う', 'え', 'お']

🎯 正規表現の記号・メタ文字(完全版)

基本記号

import re

text = "Hello123 World!@# 改行\nタブ\t終了"

# . (ドット) - 改行以外の任意の1文字
print(re.findall(r'H.l', text))          # ['Hel']
print(re.findall(r'W...d', text))        # ['World']

# ^ - 行の始まり
print(re.findall(r'^H', text))           # ['H']

# $ - 行の終わり  
print(re.findall(r'了$', text))          # ['了']

# | - OR演算子
print(re.findall(r'Hello|World', text))  # ['Hello', 'World']

# () - グループ化
print(re.findall(r'(Hello|Hi) World', "Hello World"))  # ['Hello']

量詞(数量指定)

text = "a aa aaa aaaa b bb bbb"

# * - 0回以上
print(re.findall(r'a*', text))     # ['a', '', 'aa', '', 'aaa', '', 'aaaa', ...]

# + - 1回以上  
print(re.findall(r'a+', text))     # ['a', 'aa', 'aaa', 'aaaa']

# ? - 0回または1回
print(re.findall(r'a?b', text))    # ['b', 'b', 'b'] 

# {n} - ちょうどn回
print(re.findall(r'a{3}', text))   # ['aaa', 'aaa'](aaaaの中の最初の3つも含む)

# {n,} - n回以上
print(re.findall(r'a{3,}', text))  # ['aaa', 'aaaa']

# {n,m} - n回以上m回以下
print(re.findall(r'a{2,3}', text)) # ['aa', 'aaa', 'aaa']

文字クラス

text = "ABC123xyz!@#あいう"

# [abc] - a、b、cのいずれか1文字
print(re.findall(r'[ABC]', text))       # ['A', 'B', 'C']

# [a-z] - 小文字のアルファベット
print(re.findall(r'[a-z]', text))       # ['x', 'y', 'z']

# [A-Z] - 大文字のアルファベット  
print(re.findall(r'[A-Z]', text))       # ['A', 'B', 'C']

# [0-9] - 数字
print(re.findall(r'[0-9]', text))       # ['1', '2', '3']

# [^abc] - a、b、c以外
print(re.findall(r'[^A-Za-z0-9]', text)) # ['!', '@', '#', 'あ', 'い', 'う']

🚀 特殊シーケンス(超便利)

text = "Hello123 World!\n改行\tタブ 全角スペース"

# \d - 数字 [0-9]と同じ
print(re.findall(r'\d', text))          # ['1', '2', '3']
print(re.findall(r'\d+', text))         # ['123']

# \D - 数字以外 [^0-9]と同じ
print(re.findall(r'\D', text))          # ['H', 'e', 'l', 'l', 'o', ' ', 'W', ...]

# \w - 単語文字 [a-zA-Z0-9_]と同じ
print(re.findall(r'\w', text))          # ['H', 'e', 'l', 'l', 'o', '1', '2', '3', ...]
print(re.findall(r'\w+', text))         # ['Hello123', 'World', '改行', 'タブ', '全角スペース']

# \W - 単語文字以外
print(re.findall(r'\W', text))          # [' ', '!', '\n', '\t', ' ']

# \s - 空白文字(スペース、タブ、改行など)
print(re.findall(r'\s', text))          # [' ', '\n', '\t', ' ']

# \S - 空白文字以外
print(re.findall(r'\S+', text))         # ['Hello123', 'World!', '改行', 'タブ', '全角スペース']

🎭 グループ化とキャプチャ

text = "2025-07-10 14:30:25"

# () - キャプチャグループ
result = re.search(r'(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})', text)
if result:
    print("全体:", result.group(0))    # 2025-07-10 14:30:25
    print("年:", result.group(1))      # 2025
    print("月:", result.group(2))      # 07
    print("日:", result.group(3))      # 10
    print("時:", result.group(4))      # 14
    print("分:", result.group(5))      # 30
    print("秒:", result.group(6))      # 25

# (?:) - 非キャプチャグループ(グループ化するけど結果に含めない)
result2 = re.findall(r'(?:\d{4})-(\d{2})-(\d{2})', text)
print("非キャプチャ:", result2)       # [('07', '10')]

# 名前付きグループ
result3 = re.search(r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})', text)
if result3:
    print("年:", result3.group('year'))   # 2025
    print("月:", result3.group('month'))  # 07
    print("日:", result3.group('day'))    # 10

🏴 フラグ(オプション)

text = "Hello\nWorld\nPython"

# re.IGNORECASE (re.I) - 大文字小文字を無視
result1 = re.findall(r'hello', text, re.IGNORECASE)
print("大文字小文字無視:", result1)    # ['Hello']

# re.MULTILINE (re.M) - 複数行モード
result2 = re.findall(r'^W', text, re.MULTILINE)
print("複数行モード:", result2)        # ['W']

# re.DOTALL (re.S) - .が改行にもマッチ
result3 = re.findall(r'Hello.*Python', text, re.DOTALL)
print("改行またぎ:", result3)          # ['Hello\nWorld\nPython']

# 複数フラグの組み合わせ
result4 = re.findall(r'hello.*python', text, re.IGNORECASE | re.DOTALL)
print("フラグ組み合わせ:", result4)    # ['Hello\nWorld\nPython']

💡 実用的な例集

# メールアドレス
email_text = "連絡先: test@example.com, admin@company.co.jp"
emails = re.findall(r'\w+@\w+\.\w+(?:\.\w+)?', email_text)
print("メール:", emails)

# URL
url_text = "サイト: https://example.com, http://test.org/page"
urls = re.findall(r'https?://[\w.-]+(?:/[\w.-]*)*', url_text)
print("URL:", urls)

# 日本語の郵便番号
zip_text = "〒123-4567 東京都"
zips = re.findall(r'〒\d{3}-\d{4}', zip_text)
print("郵便番号:", zips)

# 金額(カンマ区切り)
money_text = "価格は1,234,567円です"
amounts = re.findall(r'\d{1,3}(?:,\d{3})*', money_text)
print("金額:", amounts)