JavaScript 正規表現の基礎と実装テクニック詳解

パターンマッチングとは何か?

テキストデータを操作する際、特定の規則に基づいて文字列を検索・置換・抽出するための手法が正規表現(Regular Expression)です。これにより、単一のループでは処理できない複雑な条件付き照合を効率的に行うことが可能になります。JavaScript 環境では、正規表現はオブジェクトとして扱われ、文字列に対して直接的にメソッドを適用できる機能を提供しています。

定義と作成方法

新規にパターンを構築するには、主に以下の 2 つの構成要素を使用します。

1. リテラル表記(推奨)

固定されたルールに対して最適化されており、実行速度も高速です。スラッシュで挟むことで簡潔に記述できます。

const searchPattern = /[0-9]+/;

2. コンストラクタ利用

プログラム変数を用いて動的に生成する場合や、特殊文字を含める際に適しています。柔軟性が高いため、ランタイムで決定されるルールに適しています。

const keyword = "検索語";
const dynamicPattern = new RegExp(keyword);

主要メソッド概要

正規表現オブジェクトおよび文字列オブジェクトには、パターンとの比較を行うための標準的な機能が用意されています。

メソッド名 対象 機能 出力例
test() 正規表現 一致判定を行い、true/false を返す /数字/.test('abc') → false
exec() 正規表現 最初に一致した部分の詳細情報を配列で返す /ABC/.exec('ABC') → ["ABC"]
match() 文字列 全て一致する部分をリスト形式で返す(g オプション必須) 'ABC'.match(/C/g) → ["C"]
replace() 文字列 該当部分を指定した内容に書き換える 'hello'.replace('l','L') → 'heLlo'

文法構造の分解

オプション制御

正規表現の末尾に追記することで、マッチングの挙動を変更できます。

  • g(Global): 全ての一致箇所を取得対象とする
  • i(Ignore Case): 大文字小文字の区別なし
  • m(Multi-line): 行頭尾を^\$で区切る方式に変更

エスケープ記号

通常のアルファベットとは異なる意味を持つ特別な文字群です。

  • 開始/終了: ^, $
  • 単語境界: \b(単語の始点または終点を捉える)
// 完全に一致するかのチェック
/^テスト$/.test('テスト'); // true
/^テスト$/.test('テスト 後'); // false

反復回数指定

直前の文字が何回現れるかを決めます。

演算子 意味 例
* 0 回以上 a* は空、aaa にも対応
+ 1 回以上 a+ は a か aa でないといけない
? 0 回または 1 回 a? は a または空
{n,m} n 回以上 m 回以下 3〜5 回出現要求

文字クラスと範囲

括弧内で定義されたセット内の任意の 1 文字にマッチします。

  • [abc]: a, b, c のどれか 1 つ
  • [a-z]: 小文字英字すべて
  • [^...]: 除外(括弧内以外)

プレフィックス記法

頻出する文字カテゴリを短縮コードで表します。

  • \d: 数字
  • \w: 英数字とアンダースコア
  • \s: 空白文字(改行含む)
  • .: 改行以外の任意の 1 文字

グループ化と参照

円括弧 () で囲むことで論理的なブロックを作成し、結果を後続で参照可能です。

const dateStr = '2024-01-01';
const groupPattern = /(\d{4})-(\d{2})-(\d{2})/;

// 取得したグループを再利用して形式変更
dateStr.replace(groupPattern, '$2/$3/$1'); // 01/01/2024

分岐処理

パイプ | を使うことで、「A または B」の条件設定が可能です。

const eitherPattern = /エラー | 警告 /;
eitherPattern.test('エラー発生!'); // true

業務における有効活用法

入力検証パターンの構築

ユーザー入力欄で、強度のあるパスワード要件を満たしているか確認します。

const passwordValidator = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d).{8,20}$/;
passwordValidator.test('SecurePass123'); // true
passwordValidator.test('weakpass'); // false

色コードフォーマット

CSS やデザインツールで使用される十六進数カラー値の整合性をチェックします。

const hexColor = /^#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})$/;
hexColor.test('#FFF'); // true
hexColor.test('#GGG'); // false

時刻データ校验

日付選択器などに合わせて、HH:MM 形式かつ妥当な値であるかを確認。

const timeChecker = /^([01][0-9]|2[0-3]):[0-5][0-9]$/;
timeChecker.test('23:59'); // true
timeChecker.test('25:00'); // false

プライバシー保護処理(マスク表示)

機密情報を一部隠すために、電話番号の一部を代替文字へ置換します。

const phoneNumber = '09012345678';
const maskRule = /(\d{3})\d{4}(\d{4})/;

// 前半と後半を残し、真ん中を星印にする
console.log(phoneNumber.replace(maskRule, '$1***$2')); 
// 出力:090***5678

高度な制御技術

マッチング戦略の違い

デフォルトの量詞は左端から右端へ可能な限り長く取り込もうとします(贪婪)。量詞の後に疑問符 ? をつけると最短距離で停止します(非贪婪)。

const html = '<span>content</span><span>data</span>';

// 長すぎて最後を消費してしまう場合
html.match(/<span>.*<\/span>/); 

// 最小単位で区切りたい場合は ? を追加
html.match(/<span>.*?<\/span>/g);

前方断言(Lookahead)

実際に文字を取り込むのではなく、その後の条件を満たしているかどうかのみ判定します。

  • 正則:(?=...) 後方に特定の文字列があること必須
  • 負則:(?!...) 後方に特定の文字列がないこと必須
/**
 * パスワード強制要件: 数字が連続して終わらないこと
 */
const complexCheck = /^(?!.*\d+$).{6,}/;

complexCheck.test('abc123'); // true
complexCheck.test('123456'); // false
/**
 * 強力なパスワード要件: 8〜20 文字 + 特殊文字混在
 */
const robustPwd = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@#$]).{8,20}$/;
robustPwd.test('MyP@ssword'); // true

タグ: javascript RegularExpressions StringHandling InputValidation WebSecurity

10月12日 21:23 投稿