正規表現はランダムなノイズのように見えるという評判があります。^[\w.-]+@[\w-]+\.\w{2,}$ のようなパターンは、猫がキーボードの上を歩いたかのように見えるかもしれません。しかし、この暗号のような構文の裏には、驚くほどエレガントなアイデアがあります:テキスト内のパターンを簡潔に記述するための言語です。
フォーム入力のバリデーション、ログファイルの検索、データの整形、コードベース全体での検索と置換など、regexは開発者のツールキットの中で最も汎用性の高いツールの1つです。あらゆる細かな機能を暗記する必要はありません。少数の構成要素で、実用的なユースケースの大半をカバーできます。
正規表現とは何か
正規表現(regexまたはregexp)は、文字列の集合を記述するパターンです。プログラミング言語、テキストエディタ、コマンドラインツールの検索エンジンに渡すと、マッチするすべての文字列を見つけます。
高機能な検索クエリと考えてください:
- 通常の検索: 「error」という正確な単語を見つける
- regex検索: IPアドレス、日付、メールアドレス、あるいは記述できるあらゆる構造に見えるものを見つける
正規表現は数学者のスティーブン・クリーネによって1956年に発明され、1960年代にUnixテキストエディタを通じてコンピューティングに導入されました。今日では、ほぼすべてのプログラミング言語とテキストエディタでサポートされています。
構成要素
リテラル文字
最もシンプルなregexはプレーンテキストです。パターン hello は、出現するすべての「hello」にマッチします。特別なことは何もありません。
ドット(.) — 任意の1文字
ドットは改行以外の任意の1文字にマッチします。
h.tは「hat」「hit」「hot」「h3t」さらには「h t」にもマッチします
文字クラス([])
角括弧は、1つのポジションで許可される文字のセットを定義します。
[aeiou]— 任意の母音[0-9]— 任意の数字[A-Za-z]— 任意の英字[^0-9]— 数字でない任意の文字(括弧内の^は「〜でない」を意味します)
短縮クラス
| 短縮 | 意味 | 等価 |
|---|---|---|
\d |
任意の数字 | [0-9] |
\w |
単語文字 | [A-Za-z0-9_] |
\s |
空白文字 | [ \t\n\r] |
\D |
数字以外 | [^0-9] |
\W |
単語文字以外 | [^A-Za-z0-9_] |
\S |
空白以外 | [^ \t\n\r] |
量指定子 — いくつ
量指定子は、直前の要素が何回出現すべきかを制御します。
| 記号 | 意味 | 例 | マッチ |
|---|---|---|---|
* |
0回以上 | ab*c |
"ac"、"abc"、"abbc" |
+ |
1回以上 | ab+c |
"abc"、"abbc"("ac"は不可) |
? |
0回または1回 | colou?r |
"color"と"colour" |
{3} |
ちょうど3回 | \d{3} |
"123"、"456" |
{2,4} |
2〜4回 | \d{2,4} |
"12"、"123"、"1234" |
アンカー — 位置
^— 文字列の先頭(mフラグでは各行の先頭)$— 文字列の末尾(または各行の末尾)\b— 単語境界
パターン ^\d{4}$ は「2026」のようにちょうど4桁の数字である文字列にマッチしますが、「abc2026」や「2026xyz」にはマッチしません。
グループと選択
(abc)— 「abc」をグループとしてキャプチャa|b— 「a」または「b」にマッチ(cat|dog)— 「cat」または「dog」にマッチ
グループを使えば、シーケンスに量指定子を適用することもできます:(ha)+ は「ha」「haha」「hahaha」にマッチします。
よく使う実践的なパターン
メールアドレスの基本バリデーション
^[\w.-]+@[\w-]+\.\w{2,}$
user@example.com、first.last@company.co.uk(部分的)にマッチし、@やドメインのない文字列を拒否します。
重要: メールアドレスを正規表現で完全にバリデーションすることは非常に難しいことで知られています。RFC 5322の完全な仕様は極めて複雑です。本番システムでは、基本的なregexでフォーマットチェックを行い、確認メールを送信してアドレスを検証してください。
電話番号のマッチ
\+?\d{1,3}[-.\s]?\(?\d{1,4}\)?[-.\s]?\d{3,4}[-.\s]?\d{3,4}
+1 555 123 4567、555-123-4567、(555) 123-4567 のような形式に対応します。
URLのマッチ
https?://[\w.-]+(/[\w./?&=-]*)?
https://example.com、http://example.com/path?q=hello にマッチします。
日付のマッチ(YYYY-MM-DD)
\d{4}-\d{2}-\d{2}
2026-03-29、1999-12-31 にマッチします。注意:これはフォーマットのみをチェックし、有効性は確認しません。9999-99-99 にもマッチしてしまいます。
動作を変えるフラグ
ほとんどのregexエンジンは、パターンの適用方法を変更するフラグをサポートしています:
| フラグ | 名前 | 効果 |
|---|---|---|
g |
グローバル | 最初の一致だけでなく、すべての一致を検索 |
i |
大文字小文字無視 | hello が "Hello"、"HELLO" などにマッチ |
m |
マルチライン | ^ と $ が各行の先頭・末尾にマッチ |
s |
Dotall | . が改行文字にもマッチ |
JavaScriptでは、フラグは閉じスラッシュの後に追加します:/hello/gi。Pythonでは、引数として渡します:re.findall(r"hello", text, re.IGNORECASE)。
regexが過剰な場合
regexは強力ですが、常に最適なツールとは限りません:
- HTMLやXMLのパース。 適切なDOMパーサーを使ってください。regexはネストされたタグを確実に処理できません。
- JSONのパース。
JSON.parse()や同等のものを使ってください。regexはエッジケースで壊れます。 - 複雑なバリデーション。 パターンが複数行にわたり、読むのに5分かかるようなら、手続き型のバリデーションコードを書くことを検討してください。
- 単純な文字列操作。
startsWith()、includes()、split()だけで済むなら、プレーンな文字列メソッドの方がクリアで高速です。
よくある落とし穴
- 特殊文字のエスケープ忘れ。 ドット
.は任意の文字にマッチします。リテラルのドットにマッチさせるには\.を使ってください。(、)、[、]、+、*、?、{、}、^、$、|、\も同様です。 - 貪欲 vs 怠惰マッチング。 デフォルトでは
.*は貪欲で、できるだけ多くにマッチします。?を追加して怠惰にします:.*?はできるだけ少なくマッチします。これは区切り文字の間のコンテンツを抽出する際に重要です。 - 壊滅的なバックトラッキング。
(a+)+のようなネストされた量指定子は、特定の入力に対してエンジンが指数的な数のパスを試行し、プログラムがフリーズする原因になります。重複するパターンでのネストされた繰り返しを避けてください。 - アンカーの付け忘れ。
^と$がないと、パターンは部分文字列にマッチします。\d{3}は「abc12345」の中の「123」にマッチします。完全一致が必要なら^\d{3}$を使ってください。
さらに詳しく
regexを学ぶ最良の方法は実験することです。パターンを入力し、テストテキストを貼り付けて、何がハイライトされるか見てみましょう。各パーツがどう機能するか理解できるまで調整と反復を繰り返してください。
- Regexパターンのテスト方法 — 例付きのインタラクティブチュートリアル
- Regexテスター — パターンとテストデータを貼り付けて、マッチをリアルタイムでハイライト表示
