正規表現の基本
正規表現(regex)は、テキストを記述するパターンです。このガイドでは、よく使う基本要素と、照合が遅くなったり予想外の一致が起きたりする落とし穴を説明します。
リテラルと文字クラス
ほとんどの文字はその文字自身に一致します。パターン cat はテキスト「cat」を見つけます。. * + ? ( ) [ ] { } ^ $ | \ のように特別な意味を持つ文字もあります。これらを文字どおりに一致させるには、バックスラッシュでエスケープします。たとえばピリオドなら \. です。
文字クラスは、集合の中の1文字に一致します。[abc] は a、b、c のいずれかに、[a-z] は ASCII の小文字1文字に、[^0-9] は数字以外の文字に一致します。よく使う短縮形は \d(数字)、\w(英字、数字、アンダースコア)、\s(空白文字)と、その逆の \D、\W、\S です。ドット . は改行以外の任意の文字に一致します。
JavaScript では、\w と \d は ASCII 文字だけを対象とします。あらゆる言語の文字に一致させるには、u フラグとともに \p{L} のような Unicode プロパティを使います。
量指定子とアンカー
量指定子は、直前の要素を何回繰り返せるかを指定します。
| 構文 | 意味 | 例 |
|---|---|---|
* |
0回以上 | ab* は a、ab、abbb に一致 |
+ |
1回以上 | \d+ は 7 や 2026 に一致 |
? |
0回か1回 | colou?r は color と colour に一致 |
{n,m} |
n 回以上 m 回以下 | \d{2,4} は2〜4桁の数字に一致 |
アンカーは文字ではなく位置に一致します。^ は入力の先頭、$ は入力の末尾(m フラグを使うと各行の先頭と末尾)です。\b は単語の境界なので、\bcat\b は「cat」を見つけますが、「concatenate」の中の cat には一致しません。値全体を検証するときは、両端をアンカーで固定します。^\d{5}$ は、ちょうど5桁の数字だけを受け付けます。
グループとキャプチャ
括弧はパターンの一部をグループにまとめ、量指定子や選択をそこに適用します。(ab)+ は「ab」を繰り返し、(jpg|png) はどちらかの単語に一致します。通常のグループは一致したテキストをキャプチャもし、置換で $1、$2 などとして再利用できます。
(?<year>\d{4}) のような名前付きグループを使うとパターンが読みやすくなり、$<year> として参照できます。グループ化だけが必要な場合は、キャプチャしないグループ (?:...) を使えば不要なキャプチャを作らずに済みます。LeedyBox の正規表現テスターは、各一致をキャプチャグループとともに一覧表示し、置換結果をプレビューします。
フラグ
フラグはパターン全体の動作を変えます。JavaScript でよく使うフラグは次のとおりです。
g(global): 最初の一致だけでなく、すべての一致を検索します。i(ignore case): 大文字と小文字を同じものとして扱います。m(multiline):^と$が各改行位置でも一致します。s(dotAll):.が改行にも一致します。u(unicode): Unicode に対応した照合と\p{...}クラスを有効にします。
JavaScript には y(sticky)と d(一致位置のインデックス)もあり、テスターはこれらにも対応しています。
最長一致と最短一致、壊滅的なバックトラッキング
量指定子は既定では最長一致(貪欲)です。できるだけ多く一致させ、パターンの残りが一致しなければ文字を1つずつ戻します。テキスト <b>bold</b> に対して、パターン <.+> は文字列全体に一致します。? を付けると量指定子が最短一致になり、<.+?> は <b> だけに一致します。<[^>]+> のような否定の文字クラスのほうが、明確で速いことがよくあります。
JavaScript を含むほとんどの正規表現エンジンはバックトラッキングを使います。(a+)+$ のようなネストした量指定子や重なり合う選択肢があると、一致に失敗したときにエンジンが膨大な数の組み合わせを試すことになり、ページやサーバーが固まることがあります。これは壊滅的なバックトラッキングと呼ばれ、信頼できない入力に対してはサービス拒否攻撃(ReDoS)に悪用されることがあります。同じ文字に対して量指定子をネストすることは避け、.* よりも具体的な文字クラスを使い、一致しない長い入力でパターンをテストしてください。
正規表現の方言は異なる
正規表現に単一の標準はありません。JavaScript、Python、Java、.NET、PCRE(PHP で使用)、Go、データベースは、それぞれ少しずつ異なる構文に対応しています。後読み、強欲な量指定子、名前付きグループの構文、Unicode クラス、置換の構文が異なります。たとえば Go の RE2 エンジンは、先読み・後読みや後方参照に対応していません。
LeedyBox の正規表現テスターは、お使いのブラウザの JavaScript エンジンを使います。そこで動作するパターンでも、別の言語では変更が必要な場合があるため、実際に実行する環境で改めてテストしてください。
よくある質問
パターンが最初の一致にしか一致しないのはなぜですか?
g フラグがないと、JavaScript は最初の一致で止まります。すべての一致を見つけるには g を有効にしてください。
正規表現でメールアドレスを検証できますか?
正規表現では値がそれらしい形式かどうかは確認できますが、そのアドレスが実在するかは確認できません。確認には、確認メールを送るのが一般的な方法です。
複数行のテキストで ^ が1回しか一致しないのはなぜですか?
既定では、^ と $ は入力全体を対象とします。各行の先頭と末尾で一致させるには、m フラグを有効にしてください。