正規表現(regex)のパターンとは、テキスト内の特定の文字列にマッチする再利用可能なテンプレートのことです。ほぼすべてのプログラミング言語で動作する、いわば「超強力な検索ツール」と考えてください。メールアドレスのバリデーション、フォームから電話番号を抽出する処理、ログファイルのパースなど、よく使われる正規表現パターンをいくつか押さえておくだけで、日常的なニーズの90%に対応できます。このガイドでは、実務で役立つパターンを厳選して解説し、それぞれの動作と応用方法を丁寧に説明します。
目次
正規表現の構文クイックリファレンス
パターンの説明に入る前に、頻繁に登場する基本的な構成要素をまとめたチートシートを確認しておきましょう。正規表現を使ったことがある方も、一か所にまとめておくと便利です。
| トークン | 意味 | マッチ例 |
|---|---|---|
.
|
改行以外の任意の1文字 |
a.c
は
abc
や
a1c
にマッチ
|
\d
|
任意の数字(0-9) |
\d\d
は
42
にマッチ
|
\w
|
単語文字(英字・数字・アンダースコア) |
\w+
は
hello_world
にマッチ
|
\s
|
空白文字(スペース・タブ・改行) |
\s+
は複数のスペースにマッチ
|
^
/
$
|
文字列の先頭 / 末尾 |
^\d+$
は
123
のみにマッチ
|
{n,m}
|
n回以上m回以下の繰り返し |
\d{2,4}
は
12
から
1234
にマッチ
|
[abc]
|
文字クラス - a、b、cのいずれか |
[aeiou]
は任意の母音にマッチ
|
(?:...)
|
非キャプチャグループ | 後方参照を保存せずにグループ化 |
(?=...)
|
肯定先読み | 文字を消費せずに後続の条件を確認 |
JavaScript の正規表現構文については、 MDN Web Docs の正規表現ガイド が最も充実したリファレンスです。以下で紹介するパターンのほとんどは、フラグの書き方が多少異なるだけで、Python・PHP・Java・Ruby にもそのまま応用できます。
メールアドレスのバリデーション
メールアドレスは正規表現の定番ユースケースですが、厳格にしすぎて失敗するケースも多いです。
RFC 5322 の仕様
では技術的に
"very unusual"@example.com
のようなアドレスも許可されていますが、ほとんどの正規表現では対応していません。実務での入力バリデーションには、次のような現実的なパターンを使うのがベストです。
^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$
各パーツの解説:
-
[a-zA-Z0-9._%+\-]+- ローカル部分(@より前)。ドット・プラス・ハイフン・アンダースコアを許可 -
@- @記号そのもの -
[a-zA-Z0-9.\-]+- サブドメインを含むドメイン名 -
\.[a-zA-Z]{2,}- 2文字以上のTLD(.io、.com、.museum など)
URLとウェブアドレス
URLのパターンマッチングは、プレーンテキストからリンクを抽出する処理から、ユーザーが入力したウェブサイトURLのバリデーションまで幅広く活用できます。
https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&\/=]*)
-
https?-httpとhttpsの両方にマッチ -
(?:www\.)?- www プレフィックスはオプション -
[-a-zA-Z0-9@:%._+~#=]{1,256}- ホスト名の文字(最大256文字) -
\.[a-zA-Z0-9()]{1,6}- TLD -
\b(?:[-a-zA-Z0-9()@:%_+.~#?&\/=]*)- パス・クエリ文字列・フラグメントはオプション
抽出ではなくバリデーションだけが目的の場合は、
^
と
$
のアンカーで囲んでください。
電話番号
電話番号は国やユーザーの入力習慣によってフォーマットが大きく異なるため、扱いが難しいデータの一つです。次の2つのパターンでほとんどのケースに対応できます。
米国・カナダ(NANP)形式
^(\+1[-.\s]?)?(\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}$
マッチ例:
555-867-5309
、
(555) 867 5309
、
+1.555.867.5309
、
5558675309
国際形式(E.164 形式)
^\+[1-9]\d{6,14}$
E.164 は Twilio や AWS SNS などほとんどのテレフォニー API で使われる形式です。
+
と国番号で始まり、スペースや記号は含みません。
日付と時刻
日付のパターンマッチングは、ログパーサー・フォームバリデーター・データパイプラインなど様々な場面で必要になります。対象とするフォーマットは入力元によって異なります。
ISO 8601(YYYY-MM-DD)
^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$
米国形式(MM/DD/YYYY)
^(0[1-9]|1[0-2])\/(0[1-9]|[12]\d|3[01])\/\d{4}$
24時間表記(HH:MM または HH:MM:SS)
^([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d))?$
これらのパターンはあくまでフォーマットを検証するものであり、カレンダー上の論理チェックは行いません。たとえば
2024-02-31
(2月31日は存在しない)もマッチしてしまいます。厳密な日付バリデーションが必要な場合は、正規表現チェックの後に各言語の日付ライブラリでパースしてください。
パスワード強度のバリデーション
パスワードのルールでは通常、複数の文字種と最低文字数の組み合わせが求められます。先読みを使えば、複数の条件チェックをすっきりまとめられます。
最低8文字・大文字1文字以上・小文字1文字以上・数字1文字以上
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,}$
強力: 8文字以上・大文字・小文字・数字・特殊文字を含む
^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]).{8,}$
各
(?=.*[...])
は文字列全体をスキャンして、条件に合う文字が少なくとも1つあるかを確認する先読みです。最後の
.{8,}
が最低文字数を保証します。
{8,}
を
{12,}
に変更すれば12文字以上を要求でき、
NIST SP 800-63B のガイドライン
に準拠した設定になります。
IPアドレス
IPv4
^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$
各オクテットを0-255の範囲で明示的にマッチさせることで、
999.0.0.1
のような無効な値を正しく弾きます。
IPv6(簡略版)
^([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$
8グループのフルフォーマットに対応しています。ループバックアドレスの
::1
のような省略記法には、パターンが大幅に複雑になります。そのような場合は、正規表現よりもネットワークライブラリでパースする方が確実です。
HTMLとマークアップ
ここでは、ピンポイントに使える便利なパターンをいくつか紹介します。「HTMLを正規表現でパースするな」という一般的なアドバイスは、ドキュメント全体を対象とする場合には今でも有効です。その場合は BeautifulSoup や DOMParser のような適切なDOMパーサーを使ってください。ただし、特定の限定されたタスクであれば正規表現で十分対応できます。
すべてのHTMLタグを除去する
<[^>]*>
特定タグの内容を抽出する(例: <title>)
([^<]*)<\/title>
キャプチャグループ1にタイトルのテキストが格納されます。
HTMLの16進数カラーコードにマッチする
#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})\b
3桁の短縮形(
#fff
)と6桁のフルフォーム(
#ffffff
)の両方にマッチします。
よく使うユーティリティパターン
様々なプロジェクトで頻繁に登場するパターンをまとめました。
スラッグ(URL フレンドリーな文字列)
^[a-z0-9]+(?:-[a-z0-9]+)*$
my-blog-post-2024
のような文字列にマッチします。大文字・先頭末尾のハイフン・連続するハイフンは許可しません。
クレジットカード番号(基本フォーマット・スペースなし)
^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|6(?:011|5[0-9]{2})[0-9]{12})$
-
4で始まる - Visa(13桁または16桁) -
51-55で始まる - Mastercard(16桁) -
34または37で始まる - Amex(15桁) -
6011または65で始まる - Discover(16桁)
空白の正規化(複数スペースをまとめる)
\s{2,}
マッチした箇所を単一スペースに置換することで、ユーザーの入力やスクレイピングしたテキストの乱れた空白をクリーンにできます。
数字のみ
^\d+$
英数字のみ
^[a-zA-Z0-9]+$
特定の単語を含む行にマッチ(フラグで大文字小文字を無視)
^.*\bword\b.*$
\b
の単語境界により、
password
の中にある
word
のような部分文字列へのマッチを防ぎます。
バージョン番号の抽出(semver)
\bv?(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9.]+))?(?:\+([a-zA-Z0-9.]+))?\b
v2.14.0-beta.1+build.42
のような文字列から、メジャー・マイナー・パッチ・プレリリースラベル・ビルドメタデータをキャプチャします。
フラグと実践的なヒント
正規表現パターンは、適用するフラグによって動作が変わります。よく使われるフラグは以下の通りです。
| フラグ | JS | Python | 効果 |
|---|---|---|---|
| 大文字小文字を無視 |
i
|
re.IGNORECASE
|
大文字と小文字を同一視する |
| グローバル(全件検索) |
g
|
re.findall()
|
最初のマッチだけでなく全マッチを返す |
| マルチライン |
m
|
re.MULTILINE
|
^
と
$
が文字列全体ではなく各行の境界にマッチする
|
| ドットオール |
s
|
re.DOTALL
|
.
が改行文字にもマッチする
|
デバッグの手間を省くために習慣にしておきたいポイントをまとめます。
- エッジケースで必ずテストする - 空文字列・最大長・Unicode文字・「惜しいけど無効」な文字列などを確認してください。
-
非キャプチャグループ
(?:...)を積極的に使う - マッチした内容が不要な場合は、キャプチャグループより高速でコードもすっきりします。 -
バリデーションパターンはアンカーで固定する
-
^と$を使うことで、無効な文字列の中に有効に見える部分文字列が含まれていてもすり抜けを防げます。 -
カタストロフィックバックトラッキングに注意する
-
(a+)+のようなネストした量指定子は、細工された入力によって正規表現エンジンがハングアップする原因になります。量指定子はシンプルかつ具体的に保ってください。 - パターンを作る際は正規表現テスターを活用する - regex101.com はリアルタイムでマッチの内訳を表示し、各トークンを説明してくれます。PCRE・JavaScript・Python など複数のフレーバーを切り替えて確認できます。
正規表現パターンのテストとバリデーションを、迷わず素早く
入力バリデーション用の正規表現パターンを作るなら、適切なツールがあればずっと効率的です。正規表現を使ったテキストのクリーニング・チェック・変換など、無料のデベロッパーユーティリティをぜひお試しください。
無料ツールを試す →
greedy な量指定子(
.*
など)はできるだけ多くの文字にマッチしてからバックトラックします。lazy な量指定子(
.*?
など)はできるだけ少ない文字にマッチしようとします。たとえば
bold
という文字列に対して、
<.*>
は文字列全体にマッチしますが、
<.*?>
は
だけにマッチします。デリミタで囲まれた内容を抽出したい場合は lazy な量指定子を使いましょう。
おおむね同じですが、いくつか違いがあります。Python の
re
モジュールは PCRE スタイルの構文を使い、
(?P
による名前付きグループをサポートしています。JavaScript はフラグの書き方が若干異なり、古いエンジン(ES2018以前)では後読みがサポートされていません。複数の言語にまたがって使う場合は、文字クラス・量指定子・アンカー・基本的なグループなど共通のサブセットに絞るのが安全です。
フォーマットのバリデーションに正規表現を使うこと自体は問題ありません。実際にほぼすべてのウェブフレームワークで使われています。リスクとなるのは、カタストロフィックバックトラッキングによって ReDoS(正規表現サービス拒否)攻撃を受ける可能性がある、不適切に書かれたパターンです。ネストした量指定子を避け、パターンを具体的に保ち、正規表現が実行される前に入力の長さに合理的な上限を設けるようにしてください。
多くの一般的なエンジンでは、ASCII入力に対してはどちらも同等です。違いが出るのは Unicode を扱う場合です。一部のエンジン(Unicode モードの Python 3 など)では
\d
がアラビア・インド数字など他のスクリプトの数字にもマッチします。ASCII の0-9だけに限定したい場合は、明示的に
[0-9]
を使ってください。一般的なウェブフォームのバリデーションでは、この違いがほとんど問題になることはありません。
2つのフラグが必要です。
ドットオールフラグ
(
.
が改行にもマッチするよう)と、必要に応じて
マルチラインフラグ
(
^
と
$
が文字列全体ではなく各行の境界にアンカーされるよう)です。JavaScript では
/pattern/ms
を使います。Python では
re.DOTALL | re.MULTILINE
を組み合わせます。ドットオールフラグがないと、
.
は改行で止まってしまい、パターンが複数行にまたがりません。