無料正規表現チートシート

正規表現のインタラクティブなリファレンスガイド。

ライブパターンテスト

パターンをテスト

一致なし

使い方

  1. パターンカテゴリーを閲覧するか、検索バーを使用して特定のパターンを見つけます。
  2. 正規表現を「パターンをテスト」フィールドに入力し、サンプルテキストを「テストテキスト」に入力します。
  3. フラグ(グローバル、大文字小文字を区別しない、マルチライン)を切り替えて、瞬時に強調表示された一致を確認します。

よくある質問

正規表現とは?

正規表現(regexまたはregexp)は、テキストを検索、取得、置換するために使用されるパターンです。特殊な文字と構文を使用して、見つける文字列を定義します。

フラグの目的は?

グローバル(g)はすべての一致を検索します。大文字小文字を区別しない(i)は文字の大文字小文字を無視します。マルチライン(m)は、^と$を文字列の境界ではなく行の境界に一致させます。

このチートシートをコードで使用できますか?

はい!パターンをテストして動作を確認したら、正規表現パターンをJavaScript、Python、その他の言語のコードに直接コピーします。

パターン言語の小史

正規表現は理論計算機科学の一片として生まれました。Stephen Kleene は 1956 年のニューラルネットワークに関する論文で "正則集合" を定義し、Ken Thompson は 1968 年に grep によって Unix に組み込みました。Henry Spencer のオープンソース正規表現ライブラリ(1980 年代半ば)は、その後の多くの実装の基礎になりました。Larry Wall は Perl で構文を大幅に拡張し、彼の "Perl 互換正規表現"(PCRE)は多くの現代的な言語が従う事実上の標準となりました。今日では密接に関連しながらも微妙に異なるいくつかの正規表現の方言が存在し、あるエンジンで動くパターンが別のエンジンで同じように動くとは限りません。

あなたのパターンが動くエンジン

同じ構文でもエンジンによって異なる意味になることがあります。主な系統:

このチートシートのインタラクティブテスターは JavaScript で動作するため、パターンはブラウザの JS エンジンで評価されます。ここで動くパターンが Python や PHP で異なる挙動を示すことがあります。違いの多くは基本構文ではなく高度な機能(後読み、Unicode プロパティエスケープ、後方参照)にあります。

中核となる構成要素

ほとんどすべての正規表現パターンは、次の要素から組み立てられています。

覚えておく価値のあるパターン

覚えておくと役立つほど頻繁に出てくるパターンがいくつかあります。

用途パターン
メールアドレス(基本)^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
URLhttps?://[^\s]+
米国の電話番号\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}
ISO 日付(YYYY-MM-DD)\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])
IPv4 アドレス(オクテット検証なし)\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
16 進カラー^#?([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$
行頭・行末の空白^\s+|\s+$
連続する複数のスペース\s{2,}

メール用正規表現に関する注意: RFC 5322 に完全準拠したメール検証には 6,000 文字のモンスター正規表現が必要です。上の単純な形は実際のメールアドレスの 99% を受け入れ、正当なものを拒否しません。本番では、構文を完璧に検証しようとするより、確認メールを送る方が確実です。

貪欲と lazy: よくある落とし穴

既定では、量指定子は貪欲です。全体のパターンがマッチできる範囲で、できるだけ多くマッチします。したがって <.+><a>text</a> に適用すると <a> だけでなく全体にマッチします。.+ がつかめるだけつかむからです。最小のマッチを得るには、量指定子に ? を付けます: <.+?><a></a> をそれぞれ別々にマッチさせます。貪欲か lazy かの選択は、"なぜ正規表現が期待どおりにマッチしないのか" という種類のバグで最もよくある原因の一つです。

壊滅的バックトラックと ReDoS

一部の正規表現パターンは特定の入力で失敗するのに指数時間がかかることがあり、これは ReDoS(Regular Expression Denial of Service)というサービス拒否の脆弱性の一種です。古典的な原因は (a+)+(a|aa)+ のような入れ子の量指定子を、長い a の列の後に一致しない文字を続けた入力に適用することです。エンジンは諦める前に文字列を分割するあらゆる方法を試し、その方法の数は指数的に増えます。

実例: Cloudflare の 2019 年の障害は、WAF ルールに配置された正規表現が特定の入力で壊滅的にバックトラックしたことで引き起こされました。Stack Overflow も 2016 年 7 月に同様の事件を経験しました。trim 用の正規表現(^[\s‌]+|[\s‌]+$)が、約 20,000 文字の連続した空白を含む単一コメントで指数的バックトラックに陥り、サイトは 34 分間ダウンしました。防御的な習慣: 入れ子の量指定子を避ける、サポートされている場合は原子グループ((?>...))を優先する、信頼できない入力には RE2 や線形時間エンジンの使用を検討してください。

言語ごとに知っておく価値のある癖

正規表現を使うべきでない場面

Jamie Zawinski の有名な 1997 年の一言: "問題に直面したとき、ある人は『そうだ、正規表現を使おう』と思う。今や彼らには問題が二つある。"

よくある間違い

  1. 特殊文字のエスケープを忘れる。 .*?+()[]{}\^$|/ はすべて特殊な意味を持ちます。リテラルとしてマッチさせるには、バックスラッシュを前に付けてください。
  2. 貪欲な量指定子が多く消費しすぎる。 最小のマッチが欲しいときは ? を付けて lazy にしてください。
  3. グローバルフラグを忘れて、最初の一致しか表示されない理由を悩む。 JavaScript の String.prototype.match()g フラグなしでは最初の一致しか返しません。
  4. 長い入力での壊滅的バックトラック。 (a+)+ のような入れ子の量指定子は特定の入力で停止することがあります。境界ケースでテストしてください。
  5. 同じ正規表現がすべての言語で同じように動くと仮定する。 後読み、Unicode エスケープ、文字クラスの略記はすべて異なります。
  6. メールを厳格に検証しようとする。 技術的に正しい RFC 5322 の正規表現は保守不能です。単純な正規表現と登録時の確認メールが現実的なパターンです。
  7. HTML、JSON、CSV に正規表現を使う。 適切なパーサを使ってください。最初に節約した時間は、後でバグで失うことになります。

その他のよくある質問

ここでは動くのに、自分のコードで失敗するのはなぜ?

最もよくある原因はエンジンの違いです。JavaScript の RegExp は PCRE がサポートする一部の機能をサポートしません(逆もまた然り)。よくある落とし穴: 後読みは JS には遅れて追加され(ES2018)、名前付きグループの構文は微妙に異なり、Unicode プロパティエスケープは u フラグが必要で、[[:alpha:]] のような POSIX 文字クラスは JS にはほぼありません。デプロイ先のエンジンでテストしてください。

複数行にまたがってマッチする "グローバル" な方法はある?

二つのフラグが連動します。m(複数行)フラグは ^$ を文字列全体ではなく各行の先頭・末尾にマッチさせます。s(dotall)フラグは . を改行にもマッチさせます。グローバルの g と組み合わせれば、行をまたぐパターンで全マッチを取得できます: /^foo.+$/gms

パターンとテキストはどこかへ送信される?

いいえ。パターン照合はブラウザ組み込みの JavaScript RegExp エンジンを使っています。サーバには何もアップロードされません。これは実際の本番ログデータ、内部 API のレスポンス、機密性のあるコンテンツに対してパターンをテストするときに重要です。

後読みは学ぶべき?

便利ですが必須ではありません。後読みを使うと、何かの後に続くテキストを、その "何か" をマッチに含めずにマッチできます。例: (?<=\$)\d+ はドル記号を消費せずに、ドル記号の後の数字にマッチします。PCRE、現代の JavaScript(ES2018 以降)、Python の regex モジュールでサポートされています。可搬性のあるパターンを書くなら、まず対象エンジンを確認してください。

(...) ではなく (?:...) を使うのはなぜ?

キャプチャなしグループ((?:...))はわずかに高速で、キャプチャ配列のスロットを使わず、マッチ結果をすっきり保ちます。選択や量指定のためにグループ化が必要だが、マッチしたテキストを取り出す必要がない場合はいつでも使ってください。(http|https):// は不要かもしれないキャプチャを作りますが、(?:http|https):// は作りません。

Unicode 文字をマッチさせる正しい方法は?

JavaScript では u フラグを付けて Unicode プロパティエスケープを使います: /\p{Letter}+/gu はあらゆる文字体系の文字列に連続してマッチします。u フラグなしだと \w は ASCII の単語文字にしかマッチしません。Python の re モジュールは Python 3 では既定で Unicode 対応です。Java では Pattern.UNICODE_CHARACTER_CLASS が必要です。ほとんどのエンジンには Unicode 対応する手段があるので、お使いのエンジンのドキュメントを確認してください。

関連ツール

無料の JSON フォーマッタ&バリデータ・オンライン 無料URLエンコーダー/デコーダー 大文字小文字変換