Python | 正規表現テンプレート集(raw 文字列版)

Python
スポンサーリンク

ここでは、先ほどの validate(value, type) を拡張して、
AI的に「なぜダメなのか?」を説明するバリデーション関数 に仕上げます。


目標

通常の True / False 判定に加えて:

  • ❌ エラーの場合 → 人間が理解できる理由を説明
  • ✅ OK の場合 → 簡潔な成功メッセージ
  • (内部的には「簡易AI診断」ロジックを追加)

完成コード:AI補助つきバリデーション関数

import re

# ===== 各種正規表現パターン =====
patterns = {
    "email": re.compile(r"""
        ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$
    """, re.VERBOSE),

    "phone": re.compile(r"""
        ^0\d{1,4}-?\d{1,4}-?\d{3,4}$
    """, re.VERBOSE),

    "date": re.compile(r"""
        ^(19|20)\d{2}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
    """, re.VERBOSE),

    "url": re.compile(r"""
        ^(https?|ftp)://[A-Za-z0-9.-]+(\.[A-Za-z]{2,})+(/[A-Za-z0-9._~:/?#@!$&'()*+,;=%-]*)?$
    """, re.VERBOSE),

    "postal": re.compile(r"""
        ^\d{3}-?\d{4}$
    """, re.VERBOSE)
}

# ===== エラー診断(簡易AIロジック) =====
def diagnose_error(value: str, type_: str) -> str:
    """入力値のどこが間違っているかを人間的に説明"""
    v = value.strip()

    if type_ == "email":
        if "@" not in v:
            return "「@」が含まれていません。例:user@example.com のように入力してください。"
        if not re.search(r"\.[A-Za-z]{2,}$", v):
            return "トップレベルドメイン(.com や .jp など)がありません。"
        if " " in v:
            return "空白が含まれています。メールアドレスに空白は使えません。"
        return "メールアドレスの形式が正しくありません。"

    elif type_ == "phone":
        if not v.startswith("0"):
            return "電話番号は 0 から始まる必要があります。"
        if len(re.sub(r"\D", "", v)) < 10:
            return "数字が足りません。固定電話は10桁、携帯は11桁が一般的です。"
        return "電話番号の形式(ハイフン位置など)が不正です。"

    elif type_ == "date":
        if not re.match(r"^\d{4}-", v):
            return "西暦4桁とハイフン(YYYY-)で始めてください。"
        parts = v.split("-")
        if len(parts) != 3:
            return "年月日をハイフンで区切ってください(例:2025-11-02)。"
        try:
            y, m, d = map(int, parts)
            if not (1 <= m <= 12):
                return f"月の値が不正です({m})。01〜12 の範囲にしてください。"
            if not (1 <= d <= 31):
                return f"日の値が不正です({d})。01〜31 の範囲にしてください。"
        except ValueError:
            return "日付に数字以外が含まれています。"
        return "存在しない日付の可能性があります。"

    elif type_ == "url":
        if not re.match(r"^(https?|ftp)", v):
            return "URLは http:// または https:// で始めてください。"
        if " " in v:
            return "空白が含まれています。URLに空白は使えません。"
        return "URLの形式が不正です。ドメイン名やパスを確認してください。"

    elif type_ == "postal":
        if "-" not in v and len(v) != 7:
            return "郵便番号は7桁または 3桁-4桁 の形式で入力してください。"
        if not re.match(r"^\d{3}-?\d{4}$", v):
            return "数字以外の文字が含まれています。"
        return "郵便番号の形式が不正です。"

    return "不明な入力エラーです。"


# ===== メイン関数 =====
def validate(value: str, type_: str, verbose: bool = True) -> bool:
    """
    指定された type_ に応じて value を検証し、
    失敗時は人間向けに理由を説明する。
    """
    pattern = patterns.get(type_)
    if not pattern:
        raise ValueError(f"未知のタイプです: {type_}")

    result = bool(pattern.match(value))

    if verbose:
        if result:
            print(f"✅ {type_} OK → {value}")
        else:
            reason = diagnose_error(value, type_)
            print(f"❌ {type_} NG → {value}\n   ┗ 理由: {reason}")

    return result
Python

使用例

validate("user@example.com", "email")          # ✅
validate("userexample.com", "email")           # ❌ 「@」が含まれていません
validate("03-1234-5678", "phone")              # ✅
validate("123456", "phone")                    # ❌ 桁数不足
validate("2025-11-02", "date")                 # ✅
validate("2025-13-40", "date")                 # ❌ 月と日が不正
validate("https://python.org", "url")          # ✅
validate("python.org", "url")                  # ❌ プロトコルなし
validate("100-0001", "postal")                 # ✅
validate("100000", "postal")                   # ❌ 桁数不足
Python

出力例

✅ email OK → user@example.com
❌ email NG → userexample.com
   ┗ 理由: 「@」が含まれていません。例:user@example.com のように入力してください。
✅ phone OK → 03-1234-5678
❌ phone NG → 123456
   ┗ 理由: 電話番号は 0 から始まる必要があります。
✅ date OK → 2025-11-02
❌ date NG → 2025-13-40
   ┗ 理由: 月の値が不正です(13)。01〜12 の範囲にしてください。
✅ url OK → https://python.org
❌ url NG → python.org
   ┗ 理由: URLは http:// または https:// で始めてください。
✅ postal OK → 100-0001
❌ postal NG → 100000
   ┗ 理由: 郵便番号は7桁または 3桁-4桁 の形式で入力してください。

構造まとめ

関数名役割
validate(value, type_)入力を正規表現で検証し、エラーメッセージを表示
diagnose_error(value, type_)各種フォーマットのエラー理由をAI風に推測

発展アイデア

次のステップでは以下のように拡張できます:

  1. 🔍 エラーレベル付き出力
    軽微(typo)/致命(構造崩壊)をレベル分類
  2. 🧠 ChatGPT風診断モード
    → 「もしかして ‘user@example.com’ のようにしたかったですか?」を提案
  3. 💻 Webフォーム(HTML+JS)版
    → 入力欄に即エラー理由を吹き出し表示
Python
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました