タイトル: RegExp
SEOタイトル: JavaScript RegExp 完全ガイド(正規表現リテラル / コンストラクタ / フラグ / test / exec / match / replace)
| この記事の要点 |
|
RegExp とは
RegExp(Regular Expression)は JavaScript で正規表現を扱うためのビルトインオブジェクトです。文字列のパターンマッチング、検索、置換、抽出に使用します。フォームのバリデーション、ログのパース、テンプレート置換など、文字列処理の基盤として欠かせない機能です。
2 通りの生成方法
リテラル記法(推奨)
// /pattern/flags 形式
const re = /^[A-Z][a-z]+$/;
const re2 = /hello/gi;
コンストラクタ記法
// 動的にパターンを組み立てるときに使う
const word = 'hello';
const re = new RegExp(word, 'gi');
// バックスラッシュは文字列としてエスケープが二重に必要
const re2 = new RegExp('\\d+', 'g'); // \d+
| 方式 | 特徴 | 適した場面 |
|---|---|---|
| リテラル | コンパイル時に生成、エスケープが楽 | 固定パターン |
| コンストラクタ | 実行時に生成、変数を埋め込める | 動的パターン |
主要メソッド
test() — 一致するか判定
const re = /\d+/;
console.log(re.test('abc123')); // true
console.log(re.test('hello')); // false
exec() — 一致部分を取得
const re = /(\d+)-(\d+)/;
const result = re.exec('phone: 080-1234');
console.log(result[0]); // "080-1234"
console.log(result[1]); // "080"
console.log(result[2]); // "1234"
String 側から使う
| メソッド | 役割 | 例 |
|---|---|---|
str.match(re) | 一致を配列で返す | 'a1b2'.match(/\d/g) → ['1','2'] |
str.matchAll(re) | 全一致をイテレータで(g 必須) | [...str.matchAll(re)] |
str.replace(re, s) | 置換 | 'abc'.replace(/b/, 'B') → 'aBc' |
str.replaceAll(re, s) | 全置換(re なら g 必須) | 'a-b-c'.replaceAll('-', '_') |
str.split(re) | 分割 | 'a,b;c'.split(/[,;]/) → ['a','b','c'] |
str.search(re) | 一致位置を返す | 'abc123'.search(/\d/) → 3 |
フラグ一覧
| フラグ | 意味 |
|---|---|
g | global — 全件マッチ |
i | ignoreCase — 大文字小文字を無視 |
m | multiline — ^ $ が行頭/行末にマッチ |
s | dotAll — . が改行にもマッチ |
u | unicode — Unicode 対応(サロゲートペア / \u{}) |
y | sticky — lastIndex 位置から開始 |
d | indices — 一致位置のインデックスも返す(ES2022) |
よく使うパターン
// メールアドレス(簡易)
/^[\w.+-]+@[\w-]+\.[\w.-]+$/
// 半角数字のみ
/^\d+$/
// URL(http/https)
/^https?:\/\/[^\s]+$/
// 日付 YYYY-MM-DD
/^\d{4}-\d{2}-\d{2}$/
// 全角ひらがな
/^[-ゟ]+$/
// 全角カタカナ
/^[゠-ヿ]+$/
キャプチャグループ
位置キャプチャ
const re = /(\d{4})-(\d{2})-(\d{2})/;
const [, year, month, day] = '2026-06-11'.match(re);
console.log(year, month, day); // 2026 06 11
名前付きキャプチャ(ES2018+)
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const m = '2026-06-11'.match(re);
console.log(m.groups.year); // "2026"
console.log(m.groups.month); // "06"
console.log(m.groups.day); // "11"
replace の関数版
第 2 引数に関数を渡すと、マッチごとに動的に置換結果を計算できます。
// 数字を 10 倍にする
'a5b10c'.replace(/\d+/g, n => parseInt(n) * 10);
// "a50b100c"
// キャメルケース → スネークケース
'helloWorldFoo'.replace(/[A-Z]/g, c => '_' + c.toLowerCase());
// "hello_world_foo"
lastIndex とステートフルな挙動
g または y フラグ付きの RegExp は内部に lastIndex 状態を保持します。同じ re.exec() を繰り返すと次々と次のマッチが返ります。
const re = /\d+/g;
const text = 'a1 b22 c333';
let m;
while ((m = re.exec(text)) !== null) {
console.log(m[0], 'at', m.index);
// 1 at 1
// 22 at 4
// 333 at 8
}
RegExp の静的プロパティ(非推奨だがレガシー)
RegExp.$1 から RegExp.$9 までで、直前のマッチのキャプチャを参照できますが、古い記法です。新規コードでは match() や exec() の戻り値を使いましょう。
パフォーマンス
- 同じパターンを繰り返し使うなら、RegExp オブジェクトを 1 度だけ生成して再利用
- 長い文字列でのバックトラックは指数時間化するリスクあり(ReDoS)
String.includes()/String.startsWith()で済むなら正規表現は不要
FAQ
Q: new RegExp(str) で特殊文字をエスケープしたい
A: 標準のエスケープ関数はありません。str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') で自作するのが定番。
Q: match と matchAll の違い
A: match は g なしだとキャプチャ配列、g 付きだと一致文字列の配列。matchAll は常にキャプチャを含むイテレータを返すため、扱いが統一的。
Q: ReDoS を防ぐには?
A: (a+)+ のような catastrophic backtracking を避ける、所有量化子(JS 非対応のため代替で (?=...) 等を使う)、入力長を制限。
関連
- String.match — 文字列側の検索メソッド
- String.replace — 文字列側の置換メソッド
- String.split — 区切り文字で分割
- 正規表現 — パターン構文の基礎