/ /

チートシート — クリックで挿入

正規表現とは?

正規表現(regexまたはregexp)は、検索パターンを定義する文字のシーケンスです。文字列の検索、検証、テキストの抽出、置換に使用されます。正規表現は事実上すべてのプログラミング言語でサポートされており、テキスト処理を扱うすべての開発者にとって不可欠なツールです。

正規表現構文クイックリファレンス

  • . — 改行を除く任意の文字にマッチ
  • ^ / $ — 文字列(またはマルチラインモードでは行)の先頭 / 末尾
  • * / + / ? — 0回以上 / 1回以上 / 0回または1回
  • {n,m} — n回からm回の繰り返し
  • [abc] — 文字クラス — a、b、またはcにマッチ
  • [^abc] — 否定文字クラス
  • (abc) — キャプチャグループ
  • (?:abc) — 非キャプチャグループ
  • \d / \w / \s — 数字 / 単語文字 / 空白文字
  • a|b — 選択 — aまたはbにマッチ

一般的な正規表現パターン

  • メール: [\w.+-]+@[\w-]+\.[a-zA-Z]{2,}
  • URL: https?://[\w\-._~:/?#[\]@!$&'()*+,;=%]+
  • IPv4: (\d{1,3}\.){3}\d{1,3}
  • 電話番号(US): (\+1\s?)?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}
  • 16進カラーコード: #([a-fA-F0-9]{6}|[a-fA-F0-9]{3})
  • 日付(YYYY-MM-DD): \d{4}-\d{2}-\d{2}

正規表現マスター:開発者が知るべきパターン

正規表現は開発者のツールキットの中で最も強力なツールの一つですが、最も誤解されやすいものでもあります。効果的な正規表現を書く鍵は、基本的な構成要素を理解し、複雑なパターンをゼロから書こうとするのではなく、系統的に組み合わせることです。

一般的なタスクに不可欠な正規表現パターン

  • メール検証: ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ — 有効なメール形式の99%をカバーします。本番環境では、正規表現だけでなく、言語の組み込みメールバリデータの使用も検討してください。
  • URLマッチング: https?://[^\s/$.?#].[^\s]* — HTTPとHTTPS URLにマッチします。テキストからリンクを抽出するのにシンプルですが効果的です。
  • IPv4アドレス: \b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b — IPアドレス形式にマッチします。範囲の検証は行いません。
  • 日付形式(YYYY-MM-DD): \d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]) — 基本的な月/日の検証付きISO 8601日付形式にマッチします。
  • パスワード強度: ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$ — 大文字、小文字、数字、特殊文字を含む8文字以上が必要です。

正規表現のパフォーマンス:壊滅的バックトラッキングの回避

壊滅的バックトラッキングは、正規表現エンジンが特定の入力に対して指数関数的な組み合わせを試行し続けることで発生します。これによりアプリケーションがフリーズしたり、ReDoS(正規表現サービス拒否)攻撃が可能になります。

  • 危険なパターン: (a+)+$ — 入力「aaaaaaaaaaaaaaaaab」に対して、エンジンが内側と外側のグループ間でaを分割するすべての可能な方法を試すため、指数関数的な時間がかかります。
  • 安全な代替: a+$ — 可能な場合はネストされた量指定子をフラットにします。
  • 経験則: 量指定子のネスト((x+)+(x*)*(x+)*など)は、内側のパターンが外側の繰り返しと同じ文字にマッチしないことが確実でない限り避けてください。

本番アプリケーションでは、正規表現操作に常にタイムアウトを設定し、線形時間マッチングをサポートする正規表現ライブラリ(GoのRE2やRustのrust-regexなど)の使用を検討してください。

正規表現の種類:言語間の主な違い

すべての正規表現エンジンが同じではありません。重要な違いは以下の通りです:

  • JavaScript: ES2018まで後方参照のサポートなし。/pattern/flags構文を使用。gフラグはlastIndexでステートフルです。
  • Python: reモジュールを使用。名前付きグループは(?P<name>...)構文をサポートします。
  • Go: RE2エンジンを使用 — バックトラッキングなし、線形時間を保証しますが、先読み/後読みをサポートしません。
  • Java: 所有量指定子(a++)やアトミックグループを含む完全なPCREライクなサポート。

正規表現に関するよくある質問

正規表現の .* と .+ の違いは何ですか?

アスタリスク(*)は前の要素の「0回以上」を意味し、プラス(+)は「1回以上」を意味します。パターン .* は空文字列を含むあらゆる文字列にマッチしますが、.+ は少なくとも1文字必要です。どちらもデフォルトでは貪欲 — できるだけ多くマッチします。? を追加すると最短一致(できるだけ少なくマッチ)になります:.*?.+?

正規表現のフラグ g、i、m、s は何をしますか?

g(グローバル)フラグは最初のマッチで止まらずにすべてのマッチを見つけます。i フラグは大文字小文字を区別しないマッチにします。m(マルチライン)フラグは ^$ を文字列全体ではなく各行の先頭と末尾にマッチさせます。s(dotAll)フラグはドットを改行文字にもマッチさせます。フラグは必要に応じて組み合わせます:/pattern/gim

リテラルのドット、括弧、その他の特殊文字にマッチさせるにはどうすればいいですか?

特殊な正規表現文字はバックスラッシュでエスケープします。リテラルのドットは . です(バックスラッシュなしではドットは任意の文字にマッチします)。リテラルの括弧は () です。エスケープが必要なその他の文字: ^ $ | ? * + { } [ ]。例えば、URL example.com にリテラルでマッチさせるには /example.com/ と書きます — そうしなければドットは任意の文字にマッチしてしまいます。

貪欲量指定子と最短一致量指定子の違いは何ですか?

貪欲量指定子(*+{n,m})は全体のパターンがマッチする範囲でできるだけ多くマッチしようとします。最短一致(非貪欲)量指定子(*?+?{n,m}?)はできるだけ少なくマッチします。例えば、<b>bold</b> に対して、貪欲な /<.*>/ は文字列全体にマッチしますが、最短一致の /<.*?>/<b> のみにマッチします。

関連開発者ツール