JavaScript regexで文字列を判定・抽出・置換する
JavaScript regex は、パターンに対して文字列を照合し、検証・抽出・置換を行います。入力が日付、ID、コードのように予測可能な形式に従う場面では、正規表現で必要な部分を判定または取り出せます。括弧で作るキャプチャグループは一致した部分文字列を分離するため、文字列を手動で分割しなくても、1つのパターンから構造化データを取得できます。
パターン抽出を行う JavaScript Regex の例
出力:
ここに出力が表示されます...
出力:
日付を含む: true
抽出: 2024/03/15
置換後: 注文 #A-123 は 2024/03/15 に発送されました
この例の仕組み
/(\d{4})-(\d{2})-(\d{2})/は ISO 形式の日付に一致する正規表現リテラルです。\d{4}は4桁の数字に一致し、括弧は年・月・日を取り出すキャプチャグループを作ります。datePattern.test(text)は、文字列内のどこかにパターンが一致すればtrueを返します。一致の詳細は返しません。text.match(datePattern)は配列を返します。インデックス0に完全一致、その後に各キャプチャグループが入ります。一致しない場合はnullなので、ユーザー入力を解析するときは分割代入の前にガードしてください。text.replace(datePattern, "$1/$2/$3")は一致した部分文字列を置換します。$1、$2、$3は各キャプチャグループ(年、月、日)を挿入します。
JavaScript 正規表現とは?
JavaScript の正規表現は、文字列内の文字パターンに一致させるための RegExp オブジェクトです。JavaScript regexp は、リテラル(/pattern/flags)または RegExp コンストラクター(new RegExp("pattern", "flags"))で作成します。エンジンは左から右へ走査し、グローバル(g)フラグがない限り最初の一致を返します。
JavaScript Regex でよくある間違い
test や exec でグローバル正規表現を使う。
const re = /\d+/g;
console.log(re.test("abc 123")); // true
console.log(re.test("abc 123")); // false(lastIndex が進んでいる)
re.lastIndex = 0;
console.log(re.test("abc 123")); // true
g または y フラグ付きでは、test/exec は lastIndex によって状態を持ちます。真偽判定だけなら g を外すか、lastIndex をリセットしてください。
new RegExp() でエスケープを二重にし忘れる。
new RegExp("\d+"); // パターンは "d+"
new RegExp("\\d+"); // 1文字以上の数字
文字列リテラルでは \\ が1つのバックスラッシュになるため、正規表現エンジンには d ではなく \d を渡す必要があります。
正規表現リテラル vs RegExp コンストラクター
正規表現リテラル(/pattern/) | new RegExp(pattern) |
|---|---|
| 読み込み時に解析され、構文エラーを早期検出できる | 実行時にコンパイルされ、到達時にエラーが投げられる |
| 文字列エスケープが不要 | バックスラッシュを二重にする必要がある(\\d) |
| パターンはソースコード内で固定 | 変数からパターンを組み立てられる |
静的なパターンにはリテラルを使います。動的な値を含む場合はコンストラクターを使いますが、正規表現インジェクションや意図しないメタ文字解釈を防ぐため、先にユーザー入力をエスケープしてください。
const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const re = new RegExp(escapeRegExp("a+b?"), "i");
その他の例
replaceAll ですべて置換する:
const masked = "カード 4111-1111-1111-1111".replaceAll(/\d{4}/g, "****");
console.log(masked); // "カード ****-****-****-****"
検索引数が正規表現の場合、replaceAll には g フラグが必要です。g を省略すると TypeError が発生します。
matchAll ですべての一致を抽出する:
const tags = [...("#js #regex #es2022".matchAll(/#(\w+)/g))];
console.log(tags.map(m => m[1])); // ["js", "regex", "es2022"]
matchAll は一致配列のイテレーターを返し、各要素にキャプチャグループが含まれます。配列に展開すると、すべての結果へまとめてアクセスできます。
FAQ
JavaScript で正規表現をテストするには?
真偽値だけなら regex.test(string) を使い、一致の詳細が必要なら string.match(regex) を使います。複数一致を取得する場合は、g フラグ付きで string.matchAll(regex) を使うと、キャプチャグループを含む全一致のイテレーターを取得できます。
JavaScript は後読みアサーションをサポートしていますか?
はい。肯定後読み (?<=...) と否定後読み (?<!...) は多くの最新 JavaScript エンジンで使えます。ただし、古いブラウザーや一部の組み込みランタイムでは構文エラーになる可能性があります。
リテラルではなく new RegExp() を使うべきなのはいつですか?
記述時点でパターンが固定されておらず、ユーザー入力の検索語を使うような場面では RegExp コンストラクターを使います。それ以外はリテラルが適しています。二重エスケープを避けられ、構文エラーも実行前に検出できます。