正規表現 コピペで使える実践 Tips 集【中級者向け】
正規表現 コピペで即使えるパターンを、実務でよく遭遇するケース別にまとめた。基本文法は知っているが「あのパターンどう書くんだっけ」と詰まる中級者向けのリファレンス記事だ。
正規表現 コピペで使えるパターン集
メールアドレス
const EMAIL = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*\.[a-zA-Z]{2,}$/;
EMAIL.test("user@example.com"); // true
EMAIL.test("user+tag@sub.domain.jp"); // true
EMAIL.test("user@"); // false
URL
const URL_PATTERN = /^https?:\/\/(?:www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b(?:[-a-zA-Z0-9()@:%_+.~#?&/=]*)$/;
URL_PATTERN.test("https://example.com/path?q=1#hash"); // true
URL_PATTERN.test("http://localhost:3000"); // true
URL_PATTERN.test("ftp://example.com"); // false
日付(YYYY-MM-DD)
const DATE_YMD = /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$/;
DATE_YMD.test("2026-06-19"); // true
DATE_YMD.test("2026-13-01"); // false
DATE_YMD.test("2026-6-1"); // false
電話番号(日本)
// ハイフンあり・なし両対応(固定・携帯)
const JP_PHONE = /^0(?:\d-\d{4}|\d{2}-\d{3}|\d{3}-\d{2}|\d{4}-\d|\d{9}|\d{2}-\d{4}|\d{4}-\d{4})\d{4}$|^0[789]0-\d{4}-\d{4}$|^0[789]0\d{8}$/;
JP_PHONE.test("090-1234-5678"); // true
JP_PHONE.test("03-1234-5678"); // true
JP_PHONE.test("09012345678"); // true
郵便番号(日本)
const JP_POSTAL = /^\d{3}-?\d{4}$/;
JP_POSTAL.test("100-0001"); // true
JP_POSTAL.test("1000001"); // true
JP_POSTAL.test("10-001"); // false
クレジットカード番号(簡易)
const CREDIT_CARD = /^\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}$/;
CREDIT_CARD.test("4111111111111111"); // true
CREDIT_CARD.test("4111-1111-1111-1111"); // true
IPv4 アドレス
const IPV4 = /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/;
IPV4.test("192.168.0.1"); // true
IPV4.test("256.0.0.1"); // false
IPV4.test("192.168.0.256"); // false
名前付きキャプチャグループ(?<name>)
名前付きキャプチャグループを使うと、match.groups でキャプチャ結果に名前でアクセスできる。インデックス管理が不要になり、正規表現を修正してもコードが壊れにくい。
const DATE_PATTERN = /(?<year>\d{4})-(?<month>0[1-9]|1[0-2])-(?<day>0[1-9]|[12]\d|3[01])/;
const match = "2026-06-19".match(DATE_PATTERN);
const { year, month, day } = match.groups;
// year → "2026"
// month → "06"
// day → "19"
名前付きグループを replace で参照するには $<name> を使う。
const result = "2026-06-19".replace(
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/,
"$<day>/$<month>/$<year>"
);
// → "19/06/2026"
replaceAll に関数を渡すパターン。
const log = "Error at 2026-06-19, Warning at 2026-06-20";
const formatted = log.replaceAll(
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/g,
(_, _y, _m, _d, _offset, _str, groups) =>
`${groups.day}/${groups.month}/${groups.year}`
);
// → "Error at 19/06/2026, Warning at 20/06/2026"
Lookahead / Lookbehind
ゼロ幅アサーションは「前後の文字を条件にしつつ、マッチに含めない」ときに使う。
Positive lookahead (?=...)
// 数字の後に "px" が続く数値だけにマッチ
const pxValues = "10px 20em 30px".matchAll(/\d+(?=px)/g);
[...pxValues].map(m => m[0]); // ["10", "30"]
Negative lookahead (?!...)
// "foo" の後に "bar" が続かない場合にマッチ
const re = /foo(?!bar)/g;
"foobar foobaz".match(re); // ["foo"] ← "foobaz" の "foo" だけ
Positive lookbehind (?<=...)
// "$" の後に続く数値にマッチ
const prices = "$100 €200 $300".matchAll(/(?<=\$)\d+/g);
[...prices].map(m => m[0]); // ["100", "300"]
Negative lookbehind (?<!...)
// "!" が前に来ない "important" にマッチ
const re = /(?<!!)important/g;
"important !important also important".match(re); // ["important", "important"]
実用例: パスワード強度チェック
function validatePassword(pw) {
const hasUpper = /(?=.*[A-Z])/.test(pw);
const hasLower = /(?=.*[a-z])/.test(pw);
const hasDigit = /(?=.*\d)/.test(pw);
const hasSpecial = /(?=.*[!@#$%^&*])/.test(pw);
const minLength = pw.length >= 8;
return hasUpper && hasLower && hasDigit && hasSpecial && minLength;
}
validatePassword("Passw0rd!"); // true
validatePassword("password"); // false
フラグの使い分け
| フラグ | 意味 | 典型的な用途 |
|---|---|---|
g | グローバル(全マッチ) | matchAll / replaceAll |
i | 大文字小文字無視 | HTML タグ、ユーザー入力 |
m | 複数行(^/$ が行頭・行末に) | 複数行テキストのパース |
s | dotAll(. が改行を含む) | HTML/JSON の抽出 |
u | Unicode モード | 絵文字・多言語テキスト |
d | インデックス取得(ES2022) | マッチ位置の特定 |
// m フラグ: 行ごとの先頭にある ">" を除去(Markdown 引用解除)
const quoted = "> Hello\n> World";
quoted.replace(/^> /gm, ""); // "Hello\nWorld"
// s フラグ: 複数行にまたがる <script> タグを除去
const html = "<script>\nalert(1);\n</script>";
html.replace(/<script>.*?<\/script>/gs, ""); // ""
// u フラグ: 絵文字を分割せずカウント
const str = "Hello 👋 World";
[...str.matchAll(/\p{Emoji}/gu)].length; // 1(uなしだと誤カウントの恐れ)
String.prototype.matchAll の活用
match に g フラグを付けるとキャプチャグループが消える。matchAll はイテレータを返し、各マッチのキャプチャグループを保持する。
const text = "2026-01-15, 2026-06-19, 2026-12-31";
const re = /(\d{4})-(\d{2})-(\d{2})/g;
// match + g フラグ → キャプチャグループが取れない
text.match(re); // ["2026-01-15", "2026-06-19", "2026-12-31"]
// matchAll → 全マッチのキャプチャグループを取得できる
const dates = [...text.matchAll(re)].map(([, year, month, day]) => ({
year, month, day,
}));
// [
// { year: "2026", month: "01", day: "15" },
// { year: "2026", month: "06", day: "19" },
// { year: "2026", month: "12", day: "31" },
// ]
名前付きキャプチャグループと組み合わせると可読性が上がる。
const LOG = /\[(?<level>INFO|WARN|ERROR)\] (?<message>.+)/g;
const logs = `[INFO] Server started
[WARN] High memory usage
[ERROR] Connection refused`;
for (const { groups } of logs.matchAll(LOG)) {
console.log(groups.level, groups.message);
}
// INFO Server started
// WARN High memory usage
// ERROR Connection refused
正規表現のパフォーマンス注意点
ループ内での new RegExp を避ける
// Bad: ループごとにコンパイルが走る
function findBad(items, keyword) {
return items.filter(item => new RegExp(keyword, "i").test(item));
}
// Good: 外でコンパイルしてキャッシュ
function findGood(items, keyword) {
const re = new RegExp(keyword, "i");
return items.filter(item => re.test(item));
}
カタストロフィックバックトラック(ReDoS)に注意
// 危険: ネストした量指定子
// /^(a+)+$/ → "aaaaaaaaaaaaaaab" で指数的バックトラック
// 安全: アトミックグループ相当の書き換え(possessive はJS未対応のため代替)
// /(a+)/ → 内部で重複しないよう設計する
// 実例: メールの簡易チェックで使いがちなパターン
// Bad: /^([a-zA-Z0-9]+)*@/
// Good: /^[a-zA-Z0-9._%+-]+@/
test vs match vs exec の使い分け
const str = "Hello World";
const re = /world/i;
// 存在確認だけなら test が最速
re.test(str); // true
// キャプチャグループが必要なら exec(g フラグを使いまわすときも exec)
const re2 = /(\w+)/g;
let m;
while ((m = re2.exec(str)) !== null) {
console.log(m[1], m.index);
}
// Hello 0
// World 6
lastIndex のリセット忘れに注意
const re = /\d+/g;
re.test("abc123"); // true → lastIndex = 6
re.test("456def"); // false → lastIndex が 6 から再開されて見逃す
// 毎回リセットするか、test には /g を付けないのが安全
re.lastIndex = 0;
re.test("456def"); // true
まとめ
| Tips | ポイント |
|---|---|
| よく使うパターン集 | メール・URL・日付・電話番号はそのままコピペ可。要件に合わせて微調整する |
| 名前付きキャプチャグループ | (?<name>...) + groups.name でインデックス管理が不要に。replace では $<name> |
| Lookahead / Lookbehind | (?=...) (?!...) (?<=...) (?<!...) でゼロ幅アサーション。パスワード検証に特に有効 |
| フラグの使い分け | g は全マッチ、i は大文字無視、m は複数行、s はdotAll、u はUnicode |
matchAll の活用 | g フラグ + キャプチャグループが必要なら matchAll 一択。スプレッドで配列化 |
| パフォーマンス | ループ外でコンパイル・ReDoSパターンを避ける・g フラグの lastIndex に注意 |
正規表現は書き捨てにせず、定数として切り出してテストを添えておくと長期的なメンテが楽になる。vitest や jest で各パターンにスナップショットテストを書いておくのがおすすめだ。