AIに正規表現を作らせるときは、パターンより先に、受け入れる値と拒否する値を決めます。「商品コードをチェックして」だけでは、前後に文章があってもよいのか、全角数字を許すのか、改行を除いてよいのかが決まりません。
この記事では、架空の商品コードをPythonのreで検査します。条件、正規表現、実行コード、結果を一緒に残す方法です。AIへ生成を依頼した実測ではなく、説明用に作ったパターンと入力をローカルのPythonで実行した例です。他の言語や本番システムで動作確認したものではありません。
目次
文字の仕様と、検査する範囲を決める
今回は「ASCII大文字英字3文字、半角ハイフン1文字、ASCII数字3桁」の7文字だけを受け入れます。前後空白や改行を除く処理は行わず、全角から半角への正規化もしません。実際の製品仕様ではありません。
表は横にスクロールできます
| 条件 | 今回の決め方 |
|---|---|
| 目的 | 入力欄全体の形式を検証する |
| 実行環境 | Python標準のre、文字列str |
| 英字 | A〜ZのASCII大文字3文字 |
| 区切り | ASCIIのハイフン「-」 |
| 数字 | 0〜9のASCII数字3桁 |
| 前処理 | 空白削除、大小変換、正規化をしない |
| 抽出 | 今回は不要 |
入力が「説明文の中からコードを見つける」という目的なら、別の検査です。形式が合っていても、そのコードが商品台帳に存在するかは分かりません。形式検証と、存在・利用権限などの業務上の確認も分けます。
Pythonではfullmatchで全体を確認する
今回のパターンは[A-Z]{3}-[0-9]{3}です。Pythonのfullmatchへ渡し、文字列全体が一致するかを確認します。searchは文字列の途中から探すため、前後に余計な文があっても見つかる場合があります。Python公式:re(新しいタブで開く)
正規表現だけでなく、どのAPIへ、どのフラグで渡すかまで保存してください。同じパターンでも、全体検証と検索を入れ替えると用途が変わります。JavaScriptやPCREなどへ移す場合も、そのまま同じ結果と決めず、移行先の実装で同じ入力を検査します。
次が、この例の受け入れ・拒否条件です。表示上の「改行」「空文字」は説明であり、テストコードでは実際の文字を使います。
表は横にスクロールできます
| 入力 | 期待 | 確認する条件 |
|---|---|---|
| ABC-123 | 受け入れる | 基本形 |
| XYZ-999 | 受け入れる | 別の大文字と数字 |
| ABC-001 | 受け入れる | 先頭ゼロを含む数字列 |
| AB-1234 | 拒否 | 英字と数字の桁数が違う |
| ABC123 | 拒否 | ハイフンなし |
| abc-123 | 拒否 | 小文字 |
| ABC-123 | 拒否 | 全角数字 |
| ABC-123 | 拒否 | 全角英字 |
| ABC‐123 | 拒否 | 区切りがASCIIハイフンではない |
| 前に空白があるABC-123 | 拒否 | 前処理で空白を消さない |
| ABC-123の直後に改行 | 拒否 | 入力全体を検査する |
| 説明文にABC-123を含む | 拒否 | 部分検索ではない |
| 空文字 | 拒否 | 必須の7文字がない |
期待値と実行結果を照合する
次のコードでは、期待値をパターンから作らず、上の仕様から別に用意しています。\nは実行時には改行となり、reprの表示で確認できます。
import re
pattern = re.compile(r"[A-Z]{3}-[0-9]{3}")
cases = [
("ABC-123", True),
("XYZ-999", True),
("ABC-001", True),
("AB-1234", False),
("ABC123", False),
("abc-123", False),
("ABC-123", False),
("ABC-123", False),
("ABC‐123", False),
(" ABC-123", False),
("ABC-123\n", False),
("code: ABC-123", False),
("", False),
]
for value, expected in cases:
actual = pattern.fullmatch(value) is not None
print(repr(value), expected, actual)
assert actual == expected, repr(value)
このコードの13件は、ローカル実行で期待値と一致しました。実行したPythonのバージョンとケースは検証記録へ残しています。ただし、入力欄、データベース、外部APIとつないだ試験ではありません。13件が通ったことだけで、すべての入力や別の実行環境への適合を保証しません。
広すぎる条件を、拒否例で見つける
数字部分を\d{3}に変えると、PythonのUnicode文字列ではASCII以外の十進数字も対象になります。今回の条件では、全角数字の「ABC-123」を通すと誤りです。数字という言葉だけで、ASCII数字に限定されたと考えないようにします。
また、末尾を表す$は、Pythonでは文字列末尾の改行の直前にも一致します。「先頭と末尾の記号を付けたから、余分な文字は絶対に入らない」という説明だけでは不十分です。Python公式:正規表現の構文(新しいタブで開く)
今回の実行では、次の取り違えも別に確認しました。
表は横にスクロールできます
| 検査方法 | 入力 | 実行結果 | 今回の仕様との関係 |
|---|---|---|---|
search(r"[A-Z]{3}-[0-9]{3}", ...) | code: ABC-123 | 一致あり | 入力欄全体の検証には使えない |
fullmatch(r"[A-Z]{3}-\d{3}", ...) | ABC-123 | 一致あり | ASCII限定の条件より広い |
match(r"^[A-Z]{3}-[0-9]{3}$", ...) | ABC-123の直後に改行 | 一致あり | 改行を拒否する条件を満たさない |
| 採用パターンでfullmatch | ABC-123の直後に改行 | 一致なし | 今回の拒否条件と一致 |
これはPythonの指定した方法で実行した結果です。他の言語の数字クラスや末尾記号へ、そのまま一般化しません。生のパターン、文字列への書き方、API、フラグ、入力を一組で確認します。
AIには、未決の条件とテストを返させる
次の仕様の正規表現候補とテストコードを作ってください。
実行環境:[言語・ライブラリ・バージョン]。
目的:入力欄全体の形式検証。部分抽出ではありません。
文字種:ASCII大文字3文字、ASCIIハイフン、ASCII数字3桁。
前処理:空白除去、大小変換、Unicode正規化はしません。
フラグ:追加しないでください。
正常例:ABC-123、XYZ-999、ABC-001。
拒否例:全角文字、小文字、桁違い、空白、末尾改行、説明文、空文字。
出力:パターン、使用API、各条件の説明、期待値付きテストコード。
未決の条件は推測せず列挙してください。
実行していなければ、実行済みとは書かないでください。
仕様で前後空白を許すなら、除去前の値と除去後の値を区別し、前処理のテストも加えます。正規表現を直すのか、入力を変換するのかを曖昧にしないでください。コードの先頭ゼロも、数値へ変換すれば消える場合があるため、識別子の数字列として残します。
形式で扱えない条件と、未検証の負荷を残す
日付の実在、メールの到達、住所の実在などは、形が合うことと別の問題です。複雑な意味条件まで一つの式へ押し込まず、専用の解析や業務上の確認へ分けます。既存システムに検証規則がある場合は、それと競合する式を追加しないようにします。
今回の短い例では、処理時間や大量入力時の負荷を測定していません。「高速」「どんな入力でも安全」とは判断しません。実環境では受け付ける型、最大長、エラー処理、使用エンジンの制限も確認します。
採用時は、条件、パターン、APIとフラグ、実行環境、入力と期待値を一緒に保存します。誤って通した値、正しいのに拒否した値が見つかったら、まず仕様と例へ追加し、以前のケースも含めて再実行してください。AIの説明の読みやすさではなく、決めた条件と実行結果の対応で修正を判断できます。
参考資料
公式仕様の確認日:2026年10月20日。商品コードと入力は架空例です。Pythonの13ケースと取り違え4例をローカルで実行しました。AI生成、別言語、本番入力欄、負荷、業務上のコード存在確認は検証していません。
