すべての記事

正規表現:基本と貪欲マッチの罠

正規表現(regex)は、文字列のパターンを簡潔に記述する方法です。具体的な文字列そのものではなく、文字列が満たすべき「ルール」を表します。ループで1文字ずつ調べる代わりに、1つの式で複雑な構造を検索・検証できます。

基本の構成要素

  • 文字クラス\d(数字)、\w(英数字とアンダースコア)、\s(空白)、または [a-zA-Z] のような独自のクラス。
  • 量指定子*(0回以上)、+(1回以上)、?(0回または1回)、{2,5}(2〜5回)。
  • キャプチャグループ — 丸かっこ (...) でマッチの一部を取り出し、置換などで個別に利用できる。
  • アンカー^$ は行の先頭・末尾にパターンを固定する。

\w が日本語を認識しない理由

このツールが使うJavaScriptの正規表現エンジンでは、\w は常に [A-Za-z0-9_]、つまり半角英数字とアンダースコアだけを意味します。/^\w+$/.test('こんにちは')false になり、漢字はもちろん、ひらがな・カタカナも一致しません。u フラグを付けても \w 自体の定義が広がるわけではなく、日本語の文字を拾うには /^\p{L}+$/u のように Unicode プロパティの「任意の文字」クラスを明示的に使う必要があります。フォームの必須入力チェックなどで \w+ を安易に流用すると、日本語入力だけが弾かれるバグになりがちです。

貪欲マッチと非貪欲マッチ

量指定子は既定では「貪欲」で、可能な限り多くの文字を取り込もうとし、マッチが成立しない場合だけ譲歩します。たとえば <.+><a>text</a> に対して、最初の < から最後の > までをまとめて取り込んでしまいます。量指定子の後に ? を付ける(<.+?>)と「非貪欲」になり、最初にマッチした時点で止まる最小限の取り込みになります。

何に使えるか

  • 入力データの形式検証(メールアドレス、電話番号、郵便番号)。
  • 厳密一致ではなくパターンに基づく検索・一括置換。
  • ログや非構造化テキストからの構造化データ抽出。

破滅的バックトラッキング

(a+)+ のようなネストした量指定子は、特定の入力に対して正規表現エンジンに指数関数的な数の組み合わせを試させ、マッチしないと結論づけるまでに膨大な時間がかかることがあります。一見単純な式でページやサーバーが「フリーズ」する、これは実在する脆弱性クラス(ReDoS)なので、複雑な入れ子の量指定子は期待通りの入力だけでなく、長い「ほぼ一致」する文字列でも検証すべきです。

ツールを試す