正規表現とは
正規表現(Regular Expression、略して regex または regexp)は、文字列のパターンを表現するための記法だ。特定の文字の並びを「パターン」として定義し、文字列の検索・抽出・置換・バリデーションを柔軟かつ効率的に行える。
どんな場面で使うか
正規表現はプログラミングに限らず、テキストエディタやコマンドラインツール(grep、sed、awk)でも日常的に使われる。具体的な場面を挙げる。
- フォーム入力値のバリデーション(メールアドレス・電話番号・郵便番号の形式確認)
- ログファイルから特定のエラーメッセージや日付を抽出する
- HTMLやCSVなどのテキストデータを一括置換・整形する
- URLの構造解析やルーティング設定(Express・Nginxなど)
- コードエディタ(VS Code・Sublime Text)での高度な検索・置換
- Webスクレイピングで必要なデータだけを取り出す
Point
正規表現はほぼすべてのプログラミング言語でサポートされており、一度習得すれば言語をまたいで応用が利く。構文に若干の差異はあるが、コアとなる考え方は共通だ。
基本メタ文字一覧
正規表現では通常の文字に加え、特別な意味を持つ「メタ文字」を使う。まず頻出の10個を頭に入れておけば、実務のほとんどのケースに対応できる。
| メタ文字 | 意味 | 例 | マッチする文字列 |
|---|---|---|---|
. |
任意の1文字(改行以外) | a.c |
abc, aXc, a1c など |
* |
直前の要素が0回以上繰り返す | ab*c |
ac, abc, abbc, abbbc など |
+ |
直前の要素が1回以上繰り返す | ab+c |
abc, abbc(ac は非マッチ) |
? |
直前の要素が0回または1回 | colou?r |
color, colour |
^ |
行頭にマッチ | ^Hello |
"Hello world"(先頭から始まる行) |
$ |
行末にマッチ | world$ |
"Hello world"(末尾で終わる行) |
[] |
文字クラス(いずれか1文字) | [aeiou] |
a, e, i, o, u のいずれか |
() |
グループ化・キャプチャ | (ab)+ |
ab, abab, ababab など |
| |
OR(選択) | cat|dog |
cat または dog |
\ |
エスケープ(次の文字を文字通りに解釈) | \. |
ピリオド文字そのもの |
注意
メタ文字そのものを検索したいときはバックスラッシュでエスケープする。たとえばピリオド(.)を文字として検索するには \. と書く。( ) [ ] { } ^ $ * + ? | \ / などは要エスケープ。これを忘れて意図しないマッチが発生するのは初心者あるあるだ。
文字クラス(\d, \w, \s, \b)
よく使う文字のグループには省略記法の「定義済み文字クラス」が用意されている。[] でいちいち書くより大幅に簡潔になるため、積極的に使いたい。
| 記法 | 意味 | 同等の表現 | 大文字(否定形) |
|---|---|---|---|
\d |
数字(0〜9) | [0-9] |
\D(数字以外) |
\w |
単語文字(英数字+アンダースコア) | [a-zA-Z0-9_] |
\W(単語文字以外) |
\s |
空白文字(スペース・タブ・改行など) | [ \t\n\r\f\v] |
\S(空白以外) |
\b |
単語境界(単語の開始・終了位置) | — | \B(単語境界以外) |
\t |
タブ文字 | — | — |
\n |
改行文字(LF) | — | — |
文字クラスの範囲指定
[] 内では - を使って範囲を指定できる。^ を先頭に置くと否定クラス(「〜以外」の意味)になる。
量指定子
量指定子(Quantifiers)は直前の要素が「何回繰り返すか」を指定するものだ。* + ? の3つが基本で、さらに具体的な回数も指定できる。
| 量指定子 | 意味 | 例 | マッチ例 |
|---|---|---|---|
* |
0回以上 | \d* |
""(空), "1", "123" |
+ |
1回以上 | \d+ |
"1", "123"(空は非マッチ) |
? |
0回または1回 | \d? |
""(空), "1" |
{n} |
ちょうどn回 | \d{4} |
"2026"(4桁の数字) |
{n,} |
n回以上 | \d{3,} |
"123", "1234", "12345"… |
{n,m} |
n回以上m回以下 | \d{2,4} |
"12", "123", "1234" |
最長マッチと最短マッチ
デフォルトの量指定子は「最長マッチ(greedy)」で、できるだけ多くの文字にマッチしようとする。量指定子の後に ? を付けると「最短マッチ(lazy)」に切り替わり、できるだけ少ない文字にマッチするようになる。
Point
HTMLタグのパターンを書くときは最短マッチ(+? や *?)を使うことが多い。ただし複雑なHTMLのパースには正規表現より専用のパーサを使うほうが安全だ。
グループ化とキャプチャ
括弧 () を使うと複数の要素を一つのグループとして扱える。グループ化には「繰り返し単位の指定」と「キャプチャ(一致した部分の取り出し)」という2つの役割があり、これを使いこなせると正規表現が一段と強力になる。
グループ化で繰り返し単位を指定
キャプチャグループ
グループ化した部分はキャプチャグループとして後から参照できる。日付フォーマットの変換など、マッチ結果を加工する処理でよく使うパターンだ。
非キャプチャグループ
キャプチャせずにグループ化だけしたい場合は (?:...) を使う。不要なキャプチャを省くとパフォーマンスが向上するため、取り出す必要のない括弧は非キャプチャグループにする習慣をつけておくといい。
先読み・後読み
特定のパターンの「前後に何があるか」を条件として使う「ゼロ幅アサーション」も強力だ。一致した文字自体はキャプチャせず、位置だけを判定できる。
| 記法 | 種類 | 意味 |
|---|---|---|
(?=...) |
肯定先読み | 直後に指定パターンがある位置 |
(?!...) |
否定先読み | 直後に指定パターンがない位置 |
(?<=...) |
肯定後読み | 直前に指定パターンがある位置 |
(?<!...) |
否定後読み | 直前に指定パターンがない位置 |
よく使う正規表現パターン10選
実務でよく登場するパターンをまとめた。そのままコピーして使いながら、構造を少しずつ読み解いていくと身につきやすい。なお、メールアドレスのパターンについては後述のFAQに補足があるので合わせて確認してほしい。
1. メールアドレス
2. 日本の電話番号(ハイフンあり)
3. 日本の郵便番号
4. URLの検出
5. 日付(YYYY-MM-DD形式)
6. IPアドレス(IPv4)
7. パスワード強度チェック(8文字以上・英数字混在)
8. クレジットカード番号(Visa / Mastercard / 16桁)
9. HTMLタグの除去
10. 日本語文字(ひらがな・カタカナ・漢字)
JavaScript・Python・PHPでの使い方の違い
正規表現の基本構文は共通だが、各言語でのAPIや記法に差がある。特にPythonの match と search の違いは実務でよくハマるポイントなので注意したい。
JavaScript
JavaScriptでは /pattern/flags のリテラル記法が基本だ。String メソッドと RegExp オブジェクトの両方から使える。動的にパターンを生成したい場合はコンストラクタ記法を選ぶ。
Python
Pythonでは標準ライブラリの re モジュールを使う。r"pattern"(rawストリング)でバックスラッシュを書きやすくするのが慣例だ。同じパターンを複数回使う場合は re.compile() でコンパイルしておくとパフォーマンスが向上する。
PHP
PHPでは PCRE(Perl Compatible Regular Expressions)を使う preg_* 関数群が標準だ。パターンは /pattern/flags 形式でデリミタが必要な点に注意。JavaScriptに慣れた人が最初につまずきやすいポイントだ。
| 操作 | JavaScript | Python | PHP |
|---|---|---|---|
| マッチ確認 | regex.test(str) |
re.search(pat, str) |
preg_match(pat, str) |
| マッチ結果取得 | str.match(regex) |
re.findall(pat, str) |
preg_match_all(pat, str) |
| 置換 | str.replace(regex, rep) |
re.sub(pat, rep, str) |
preg_replace(pat, rep, str) |
| 分割 | str.split(regex) |
re.split(pat, str) |
preg_split(pat, str) |
正規表現テスターの活用
正規表現は書いてすぐ動くとは限らない。「動いているつもりが想定外のパターンにもマッチしていた」という経験をしたことがある人は少なくないはずだ。テスターを使ってパターンとテスト文字列を並べて確認する習慣が、バグを早期に発見する一番の近道になる。
-
パターンを入力
正規表現フィールドに試したいパターンを入力する。メタ文字の入力補助機能があるため、初心者でも迷わず使い始められる。
-
テスト文字列を貼り付け
マッチ確認したい文字列(メールアドレス一覧、ログデータなど)をテキストエリアに貼り付ける。ローカル処理なので、実際のログデータや個人情報が含まれていても安全だ。
-
マッチ結果をリアルタイム確認
マッチした部分がハイライト表示される。キャプチャグループの内容も個別に確認できる。
-
フラグを切り替えて動作確認
g(グローバル)、i(大文字小文字無視)、m(複数行)フラグをON/OFFして挙動の違いを把握する。フラグ1つで動作が変わることを体感しておくと、後の理解が速くなる。
ツールで効率化
当サイトの正規表現テスターはブラウザ上で完全動作する。入力したデータがサーバーに送信されないため、ログや個人情報を含むデータでも安心して使える。
パフォーマンスの注意点
正規表現は便利だが、書き方を誤ると極端に遅くなる「バックトラッキング爆発(Catastrophic Backtracking)」という問題が発生する。本番環境でユーザー入力を処理する場合は特に意識が必要だ。
バックトラッキング爆発とは
正規表現エンジンは、マッチに失敗すると別の経路を試みる「バックトラッキング」を行う。これが指数関数的に増大すると処理時間が膨大になる。たった数十文字の入力に対して数秒かかるといった事態が実際に起きる。
パフォーマンス改善のポイント
- 量指定子のネスト(
(a+)+のような形)を避ける - あいまいな代替(
(a|aa)+)を避け、より具体的なパターンにする - 同じ正規表現を何度も使う場合はコンパイル・キャッシュする(Pythonの
re.compile()など) - 可能なら先頭アンカー(
^)を使い、マッチ探索範囲を限定する - 非常に長い文字列に対してはストリーム処理を検討する
注意: ReDoS攻撃
バックトラッキング爆発はセキュリティ上の脆弱性にもなる。ユーザー入力をそのまま正規表現パターンに使う場合(動的生成)は特に危険で、悪意あるユーザーが意図的に処理時間を膨大にさせる「ReDoS(Regular Expression Denial of Service)」攻撃の標的になりうる。