2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptにおける正規表現設計:パターンの明示性と安全なマッチング戦略

Posted at

概要

正規表現(RegExp)は、文字列に対する検索・抽出・検証のための構文的なパターン言語である。
一方で、「短いが意味の読めない構文」が設計の障害となることも多く、誤検知や過検出・保守不能なブラックボックスを生み出す原因にもなる。

本稿では、以下の観点から正規表現を「設計可能な構文」として再定義する:

  • 正規表現の構成要素と基本構文
  • 意図を明示するための設計テクニック
  • 安全で過不足のない検証パターン
  • エスケープ・グルーピング・フラグの管理戦略
  • 具体的なユースケース(メール・URL・日付 等)

1. 正規表現の構成と基本構文

const pattern = /[A-Z]{3}-\d{4}/;
pattern.test('ABC-1234'); // true
構文 意味
. 任意の1文字
\d 数字 ([0-9])
\w 英数字 ([a-zA-Z0-9_])
+ 1回以上の繰り返し
* 0回以上の繰り返し
? 0回または1回
^ 先頭 / 否定(文脈で異なる)
$ 末尾
(...) グルーピング
` `

2. 正規表現リテラル vs コンストラクタ

const regex1 = /\d+/;
const regex2 = new RegExp('\\d+');
  • ✅ 動的に構築する場合はコンストラクタ
  • ❌ 二重バックスラッシュが必要で可読性が下がる

3. フラグによる挙動制御

フラグ 意味
g グローバル(全てに一致)
i 大文字・小文字を区別しない
m 複数行モード (^/$が行単位に)
/text/gi

4. 読める正規表現の設計戦略

✅ グループ分割してコメントを添える(xフラグ相当の自前ドキュメント)

// ISO日付フォーマット: YYYY-MM-DD
const pattern = /^(\d{4})-(\d{2})-(\d{2})$/;

→ ✅ グループ化で意味を構造化
→ ✅ 必要なら .match() でキャプチャ使用


5. ユースケース別:安全なパターン設計

✅ メールアドレス(簡易版)

const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;

→ ❗ RFC準拠ではないが現実的に十分
→ ❌ 極端に複雑なパターン(RFC5322)にはしないこと(保守不能)


✅ URL検出

const urlPattern = /https?:\/\/[^\s/$.?#].[^\s]*/i;

→ ✅ http, https 両対応
→ ❗ スキーム省略型(www.example.com)は別対応必要


✅ 数字のカンマ区切り

const numberPattern = /^\d{1,3}(,\d{3})*$/;

→ ✅ 1,00012,345,678 を検出
→ ❌ 1000 は一致しない → 明確なルールを設計に反映


✅ 日付(YYYY/MM/DD)

const datePattern = /^\d{4}\/\d{2}\/\d{2}$/;

→ ✅ 数値とスラッシュの構造を明示


6. エスケープ設計と誤検知回避

const pattern = /https:\/\/example\.com\/user\/\d+/;

→ ✅ ./ など、構文上の記号は正しくエスケープすること
→ ❗ 不要な .* は過検出・ReDoS(正規表現DoS)リスクを高める


7. RegExpを使うべきかの判断指針

① 単純な文字列検出? → includes()/startsWith() で代用可能

② 明確な構造パターンがある? → 正規表現で設計

③ 多数の条件分岐に対応? → 文字列ロジックの方が可読性高い場合も

④ パターンの再利用・キャプチャが必要? → RegExp + match() + group活用

⑤ メンテ可能な構文か? → 複雑な正規表現はドキュメント化必須

よくあるミスと対策

.* を安易に使う

/.*@gmail\.com/ // ❌ 過剰マッチング

→ ✅ [^\s@]+ など、意図を限定する構文で明示


.test() の副作用に気づかない

const regex = /\d/g;
regex.test('123'); // true
regex.test('123'); // false ❗ カーソル位置が進む

→ ✅ g フラグ付きで .test() を繰り返し使うと挙動が変わる → 初期化が必要


結語

正規表現は短く書けるが、読みにくく壊れやすい構文である。
だからこそ、「書くときではなく、読むときの視点で設計すること」が重要になる。

  • パターンは構文ではなく、“意味を持った構造”
  • 読める構文は、バグを生まない仕様書になる
  • ルールを明示し、制限を構造に刻む

ブラックボックスではなく、“意味のある定型”として書かれた正規表現こそが、保守可能な構文である。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?