正規表現テスター

自分のテキストで JavaScript の正規表現を検証できます。g・i・m・s・u フラグを切り替え、各マッチの位置とキャプチャグループを確認し、置換結果をリアルタイムでプレビューします。

入力しながら、すべてのマッチ・グループ・位置を確認。 パターンと対象テキストを入力します。各結果は位置とキャプチャグループとともに一覧表示され、不正なパターンではエンジン自身のエラーメッセージが表示されます。置換欄は replace を呼んだときの結果をそのまま示します。

/ / g
マッチ

エンジンと同じように正規表現を読む

フラグは検索方法ではなく意味を変える

5 つのフラグは好みの設定ではなく、パターンそのものを定義し直します。g がなければ検索は最初の一致で止まります。付ければエンジンは lastIndex カーソルを保持して文字列全体を走査します。グローバルな正規表現を複数回の呼び出しで使い回すと一致を飛ばしたように見えるのも、これが理由です。i は単純な ASCII のずらしではなく、Unicode のケースマッピングに従って大文字小文字を同一視します。

最も誤解されやすいのが ms です。m^$ の意味だけを変え、文字列全体ではなく行境界に錨を打ちます。. には何の影響もありません。逆に s. だけを変え、改行にも一致させます。覚えておくと役立つ呼び名は "dotall" です。u はパターンを UTF-16 コードユニットではなくコードポイント単位で動作させるため、. が絵文字を 1 単位として扱い、\u{1F600} のようなエスケープも有効になります。同時に、これまで見逃されていたエスケープがエラーになるため、既存のパターンに付けた途端に壊れることがあります。

グループ・位置・置換

丸括弧で囲んだ部分は既定でキャプチャされ、開き括弧の順に番号が振られます。置換時の $1$2 が参照するのはこの番号です。入れ子も同じ規則に従うので、((a)b) ではグループ 1 が ab、グループ 2 が a になります。選択や繰り返しのためにグループ化したいだけなら、(?:...) を使えばキャプチャを消費せず、番号も読みやすく保てます。

各マッチに表示される位置は、最初に一致した文字のオフセットです。これは聞こえる以上に重要で、異なる位置にある同一のマッチを区別でき、アンカーが期待どおり働いたかを確認でき、古典的なゼロ幅マッチの診断もできます。\d* のようなパターンはどこでも空文字列に一致するため、グローバル検索はすべての位置でマッチを見つけます。それでも処理が進むのは、マッチが空のときに実装がカーソルを強制的に前進させるからです。

バックトラックとマッチ数の上限

JavaScript を含む多くのエンジンはバックトラックを使います。パターンの一部が失敗すると、直前の分岐点に戻って別の経路を試します。通常これは目に見えません。しかし入れ子の量指定子によって経路数が指数的に増えると破滅的になります。典型例は、b を含まない長い a の並びに対する (a+)+b です。この入力はブラウザーのタブを固めることがあり、パターンがユーザー入力由来ならサービス妨害の攻撃面になります。

ほぼすべてを回避できる習慣が 2 つあります。選択肢どうしが重ならないよう .* ではなく具体的な文字クラスを使うこと、そして可能な限りアンカーを付けることです。アンカー付きの失敗はその場で棄却され、すべてのオフセットで再試行されません。本ツールは結果を 500 件で打ち切り、切り詰めた場合はその旨を表示します。暴走したパターンはページの凍結ではなく、少し遅い結果に留まります。

オープンソースに関する注記:バニラ JavaScript で実装。サードパーティライブラリは使用していません。

よくある質問

どの正規表現方言を使っていますか?
JavaScript、つまりブラウザー内蔵の ECMAScript エンジンです。Perl・PCRE・Python の記法は近いものの、後読み・名前付きグループ・一部のエスケープが異なります。
g フラグは実際に何を変えますか?
付けない場合は最初の 1 件しか返りません。付けるとエンジンが文字列全体を走査してすべての一致を返します。ここの一覧もそれで埋まります。
空のマッチが出るのはなぜですか?
`\d*` のようにパターンがゼロ文字に一致できるためです。グローバル検索はすべての位置で一致を報告し、エンジンは無限ループを避けるためカーソルを手動で進めます。
置換でキャプチャグループを参照するには?
1 番目は $1、2 番目は $2、マッチ全体は $& です。ドル記号そのものを出したい場合は $$ と書きます。
「先頭 500 件のみ表示」とは?
広すぎるパターンでページが固まらないよう、一覧を 500 件で打ち切っています。置換プレビューはテキスト全体に適用されたままです。
パターンのせいでページが重くなるのはなぜですか?
(a+)+ のような入れ子の量指定子は指数的なバックトラックを招きます。.* の代わりに具体的な文字クラスを使い、アンカーを付けて線形に保ってください。