Dev
正規表現マスターガイド2026 - パターン別実践例総まとめ
メール、URL、電話番号の検証から複雑なテキスト解析まで。実務ですぐに使える正規表現パターンと動作原理をコードと共に学びます。
Toolypet Team
Development Team
正規表現マスターガイド2026
「正規表現は難しい」という言葉、その通りです。しかし、一度習得すればテキスト処理時間を90%削減できます。
このガイドでは、実務で最もよく使われる正規表現パターンを例と共に解説します。
正規表現の基礎
基本文法
| パターン | 説明 | 例 |
|---|---|---|
. | 任意の1文字 | a.c → "abc", "a1c" |
* | 0個以上 | ab*c → "ac", "abc", "abbc" |
+ | 1個以上 | ab+c → "abc", "abbc" |
? | 0個または1個 | colou?r → "color", "colour" |
^ | 文字列の先頭 | ^Hello |
$ | 文字列の末尾 | world$ |
\d | 数字 [0-9] | \d{3} → "123" |
\w | 単語文字 [a-zA-Z0-9_] | \w+ |
\s | 空白文字 | \s+ |
文字クラス
[abc] - a, b, c のいずれか
[^abc] - a, b, c 以外
[a-z] - a から z まで
[A-Z] - A から Z まで
[0-9] - 0 から 9 まで
[a-zA-Z] - すべての英字
量指定子
{n} - 正確にn個
{n,} - n個以上
{n,m} - n個以上m個以下
* - 0個以上 ({0,})
+ - 1個以上 ({1,})
? - 0または1個 ({0,1})
グループとキャプチャ
(abc) - キャプチャグループ
(?:abc) - 非キャプチャグループ
(?<name>abc) - 名前付きグループ
\1 - 最初のグループへの後方参照
実践パターン: バリデーション
メールアドレス
// 基本パターン
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
// テスト
emailRegex.test('user@example.com'); // true
emailRegex.test('invalid-email'); // false
パターン分析:
^ - 先頭
[a-zA-Z0-9._%+-]+ - ローカルパート(1文字以上)
@ - @ 記号
[a-zA-Z0-9.-]+ - ドメイン(1文字以上)
\. - . (エスケープ)
[a-zA-Z]{2,} - TLD(2文字以上)
$ - 末尾
URL
const urlRegex = /^(https?:\/\/)?([\da-z.-]+)\.([a-z.]{2,6})([/\w .-]*)*\/?$/;
// テスト
urlRegex.test('https://example.com'); // true
urlRegex.test('https://sub.example.com/path'); // true
urlRegex.test('invalid url'); // false
電話番号(日本)
// 携帯電話
const mobileRegex = /^0[789]0-?\d{4}-?\d{4}$/;
// 固定電話
const phoneRegex = /^0\d{1,4}-?\d{1,4}-?\d{4}$/;
// テスト
mobileRegex.test('090-1234-5678'); // true
mobileRegex.test('09012345678'); // true
パスワード強度
// 最低8文字、大文字/小文字、数字、特殊文字を含む
const strongPassword = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
// パターン分析
// (?=.*[a-z]) - 小文字最低1つ(先読み)
// (?=.*[A-Z]) - 大文字最低1つ
// (?=.*\d) - 数字最低1つ
// (?=.*[@$!%*?&]) - 特殊文字最低1つ
// {8,} - 8文字以上
クレジットカード番号
// Visa
const visaRegex = /^4[0-9]{12}(?:[0-9]{3})?$/;
// MasterCard
const mastercardRegex = /^5[1-5][0-9]{14}$/;
// 全カード(ハイフン許容)
const cardRegex = /^\d{4}[- ]?\d{4}[- ]?\d{4}[- ]?\d{4}$/;
実践パターン: テキスト抽出
HTMLタグの内容抽出
const html = '<div class="title">Hello World</div>';
// タグの内容抽出
const contentRegex = /<div[^>]*>(.*?)<\/div>/;
const match = html.match(contentRegex);
console.log(match[1]); // "Hello World"
// すべてのタグを削除
const noTags = html.replace(/<[^>]*>/g, '');
console.log(noTags); // "Hello World"
URLからドメイン抽出
const url = 'https://www.example.com/path/page.html';
const domainRegex = /^(?:https?:\/\/)?(?:www\.)?([^/]+)/;
const domain = url.match(domainRegex)[1];
console.log(domain); // "example.com"
ログファイル解析
const logLine = '[2026-02-21 14:30:45] ERROR: Connection timeout at module.js:42';
const logRegex = /\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\] (\w+): (.+) at (.+):(\d+)/;
const [, datetime, level, message, file, line] = logLine.match(logRegex);
console.log({
datetime, // "2026-02-21 14:30:45"
level, // "ERROR"
message, // "Connection timeout"
file, // "module.js"
line, // "42"
});
CSV解析(カンマ区切り)
const csvLine = 'John,"Doe, Jr.",30,"New York, NY"';
// カンマで分割(引用符内のカンマは無視)
const csvRegex = /(?:^|,)("(?:[^"]*(?:""[^"]*)*)"|[^,]*)/g;
const fields = [];
let match;
while ((match = csvRegex.exec(csvLine)) !== null) {
fields.push(match[1].replace(/^"|"$/g, '').replace(/""/g, '"'));
}
console.log(fields); // ["John", "Doe, Jr.", "30", "New York, NY"]
実践パターン: 検索と置換
電話番号フォーマット
const phone = '09012345678';
// ハイフン追加
const formatted = phone.replace(/(\d{3})(\d{4})(\d{4})/, '$1-$2-$3');
console.log(formatted); // "090-1234-5678"
金額フォーマット
const amount = '1234567890';
// 千単位カンマ
const formatted = amount.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
console.log(formatted); // "1,234,567,890"
マスキング
// メールマスキング
const email = 'username@example.com';
const masked = email.replace(/(.{2})(.*)(@.*)/, '$1***$3');
console.log(masked); // "us***@example.com"
// 電話番号マスキング
const phone = '090-1234-5678';
const maskedPhone = phone.replace(/(\d{3})-(\d{4})-(\d{4})/, '$1-****-$3');
console.log(maskedPhone); // "090-****-5678"
空白整理
const text = ' Hello World ';
// 前後の空白を削除(trim)
const trimmed = text.replace(/^\s+|\s+$/g, '');
// 連続する空白を1つに
const normalized = text.replace(/\s+/g, ' ').trim();
console.log(normalized); // "Hello World"
高度な機能
先読み(Lookahead)
// 肯定先読み: (?=...)
// "foo"の後に"bar"が来る場合のみマッチ
const regex = /foo(?=bar)/;
'foobar'.match(regex); // ["foo"]
'foobaz'.match(regex); // null
// 否定先読み: (?!...)
// "foo"の後に"bar"が来ない場合のみマッチ
const regex2 = /foo(?!bar)/;
'foobaz'.match(regex2); // ["foo"]
'foobar'.match(regex2); // null
後読み(Lookbehind)
// 肯定後読み: (?<=...)
// "$"の前にある数字
const priceRegex = /(?<=\$)\d+/g;
'$100 and $200'.match(priceRegex); // ["100", "200"]
// 否定後読み: (?<!...)
// "$"の前にない数字
const nonPriceRegex = /(?<!\$)\d+/g;
'$100 and 200'.match(nonPriceRegex); // ["200"]
名前付きグループ(Named Groups)
const dateRegex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = '2026-02-21'.match(dateRegex);
console.log(match.groups.year); // "2026"
console.log(match.groups.month); // "02"
console.log(match.groups.day); // "21"
非貪欲(Non-Greedy)
const html = '<div>Hello</div><div>World</div>';
// 貪欲(デフォルト): 可能な限り多くマッチ
/<div>.*<\/div>/.exec(html)[0];
// "<div>Hello</div><div>World</div>"
// 非貪欲: 可能な限り少なくマッチ
/<div>.*?<\/div>/.exec(html)[0];
// "<div>Hello</div>"
言語別実装
JavaScript
// 作成方法
const regex1 = /pattern/flags;
const regex2 = new RegExp('pattern', 'flags');
// メソッド
regex.test(str); // boolean
str.match(regex); // 配列またはnull
str.replace(regex, replacement);
str.split(regex);
regex.exec(str); // 詳細なマッチ情報
// フラグ
// g: グローバル検索
// i: 大文字小文字を無視
// m: マルチライン
// s: dotAll (.が改行もマッチ)
// u: Unicode
Python
import re
# コンパイル
pattern = re.compile(r'pattern', re.IGNORECASE)
# メソッド
re.match(pattern, string) # 先頭からマッチ
re.search(pattern, string) # 全体で検索
re.findall(pattern, string) # すべてのマッチリスト
re.sub(pattern, repl, string) # 置換
# 例
emails = re.findall(r'[\w.+-]+@[\w.-]+\.\w+', text)
cleaned = re.sub(r'\s+', ' ', text).strip()
Go
import "regexp"
// コンパイル
re := regexp.MustCompile(`\d+`)
// メソッド
re.MatchString(s) // bool
re.FindString(s) // 最初のマッチ
re.FindAllString(s, -1) // すべてのマッチ
re.ReplaceAllString(s, r) // 置換
// 例
numbers := re.FindAllString("a1b2c3", -1)
// ["1", "2", "3"]
パフォーマンス最適化
コンパイル済み正規表現の再利用
// 遅い: 毎回コンパイル
function validate(email) {
return /^[\w.+-]+@[\w.-]+\.\w+$/.test(email);
}
// 速い: 一度コンパイル
const emailRegex = /^[\w.+-]+@[\w.-]+\.\w+$/;
function validate(email) {
return emailRegex.test(email);
}
非キャプチャグループの使用
// 不要なキャプチャ
const regex = /(https?):\/\/(www\.)?(.+)/;
// 必要ないグループは非キャプチャ
const regex = /(?:https?):\/\/(?:www\.)?(.+)/;
破滅的バックトラッキングの回避
// 危険: (a+)+ パターン
const bad = /^(a+)+$/;
'aaaaaaaaaaaaaaaaaaaaaa!'.match(bad); // 非常に遅い
// 安全: 構造を変更
const good = /^a+$/;
デバッグのヒント
Regex Testerの活用
- パターンを入力
- テスト文字列を入力
- マッチ結果のハイライトを確認
- キャプチャグループを確認
段階的な検証
// 複雑なパターンを段階的に検証
const parts = [
'^', // 先頭
'[a-zA-Z0-9._%+-]+', // ローカルパート
'@', // @
'[a-zA-Z0-9.-]+', // ドメイン
'\\.', // .
'[a-zA-Z]{2,}', // TLD
'$', // 末尾
];
const emailRegex = new RegExp(parts.join(''));
FAQ
Q1: . vs \. の違いは?
A: .は任意の文字(ワイルドカード)、\.は文字通りのドットです。
Q2: * vs + の違いは?
A: *は0個以上、+は1個以上です。
ab*c→ "ac", "abc", "abbc"ab+c→ "abc", "abbc"("ac"はマッチしない)
Q3: 大文字小文字を無視するには?
A: フラグiを使用してください。
- JavaScript:
/pattern/i - Python:
re.IGNORECASE
Q4: 改行も.でマッチさせるには?
A: sフラグ(dotAll)を使用してください。
- JavaScript:
/pattern/s - Python:
re.DOTALL
Q5: エスケープが必要な文字は?
A: \ ^ $ . | ? * + ( ) [ ] { } これらの文字は\でエスケープしてください。
まとめ
正規表現の要点:
- 基本文法:
.,*,+,?,[],() - メタ文字:
\d,\w,\s,^,$ - 量指定子:
{n},{n,},{n,m} - 高度な機能: 先読み、後読み、名前付きグループ
練習あるのみです。Regex Testerでリアルタイムにテストしてみてください。
関連ツール
| ツール | 用途 |
|---|---|
| Regex Tester | 正規表現テストとデバッグ |
| JSON Formatter | JSONフォーマット |
正規表現Regexパターンマッチング開発JavaScriptPython
著者について
Toolypet Team
Development Team
The Toolypet Team creates free, privacy-focused web tools for developers and designers. All tools run entirely in your browser with no data sent to servers.
Web DevelopmentCSS ToolsDeveloper ToolsSEOSecurity