正規表現(regex)は開発者のツールボックスで最も強力なツールの一つです。ユーザー入力の検証、ログファイルの解析、複雑な検索置換操作など、regexは比類のない精度を提供します。この正規表現完全チートシートは、アンカー、文字クラス、量指定子、グループ、先読み/後読み、フラグなど全ての主要概念をカバーしています。
基本構文:アンカーと文字クラス
アンカーと文字クラスはregexパターンの基礎です。アンカーはマッチがどこで起こるかを指定し、文字クラスはどの文字をマッチするかを定義します。
アンカー
アンカーは文字ではなく、文字列内の位置にマッチします。
| Pattern | Description | Example |
|---|---|---|
^ | Start of string (or line with m flag) | ^Hello matches "Hello World" |
$ | End of string (or line with m flag) | world$ matches "Hello world" |
\b | Word boundary | \bcat\b matches "cat" but not "catch" |
\B | Non-word boundary | \Bcat\B matches "concatenate" |
\A | Absolute start of string (Python, Ruby) | \AHello |
\Z | Absolute end of string (Python, Ruby) | bye\Z |
文字クラス
文字クラスは単一の位置で文字セットにマッチします。
| Pattern | Description | Equivalent |
|---|---|---|
[abc] | Match a, b, or c | -- |
[^abc] | Match anything except a, b, c | -- |
[a-z] | Match any lowercase letter | -- |
[A-Z] | Match any uppercase letter | -- |
[0-9] | Match any digit | \d |
. | Match any character (except newline by default) | -- |
\d | Digit | [0-9] |
\D | Non-digit | [^0-9] |
\w | Word character | [a-zA-Z0-9_] |
\W | Non-word character | [^a-zA-Z0-9_] |
\s | Whitespace (space, tab, newline) | [ \t\n\r\f\v] |
\S | Non-whitespace | [^ \t\n\r\f\v] |
特殊文字(メタ文字)
これらの文字はregexで特別な意味を持ちます。リテラルとしてマッチするにはバックスラッシュでエスケープします。
Special characters that need escaping:
. ^ $ * + ? { } [ ] \ | ( )
To match a literal dot: \.
To match a literal star: \*
To match a literal pipe: \|
To match a backslash: \\量指定子:マッチ回数
量指定子は繰り返し回数を制御します。デフォルトは貪欲で、?を付けると控えめになります。
| Greedy | Lazy | Description |
|---|---|---|
* | *? | 0 or more times |
+ | +? | 1 or more times |
? | ?? | 0 or 1 time (optional) |
{n} | {n}? | Exactly n times |
{n,} | {n,}? | n or more times |
{n,m} | {n,m}? | Between n and m times |
貪欲 vs. 控えめ
貪欲な<.*>は文字列全体にマッチし、<.*?>は最初のタグのみにマッチします。
// Input string:
const str = '<b>bold</b> and <i>italic</i>';
// Greedy: matches from first < to LAST >
str.match(/<.*>/);
// Result: '<b>bold</b> and <i>italic</i>'
// Lazy: matches from first < to FIRST >
str.match(/<.*?>/);
// Result: '<b>'グループとキャプチャ
グループは複数の文字を一つの単位として扱い、マッチした部分を抽出できます。
キャプチャグループ
(...)でマッチをキャプチャ。\1、\2で後方参照。
// Capturing group example
const dateRegex = /^(\d{4})-(\d{2})-(\d{2})$/;
const match = '2026-02-10'.match(dateRegex);
// match[0] = '2026-02-10' (full match)
// match[1] = '2026' (year)
// match[2] = '02' (month)
// match[3] = '10' (day)
// Backreference: match repeated words
const repeated = /\b(\w+)\s+\1\b/;
repeated.test('the the'); // true
repeated.test('the cat'); // false名前付きグループ
(?<name>...)で可読性が向上します。
// Named groups in JavaScript
const dateRegex = /^(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})$/;
const match = '2026-02-10'.match(dateRegex);
// match.groups.year = '2026'
// match.groups.month = '02'
// match.groups.day = '10'# Named groups in Python
import re
pattern = r'^(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})$'
m = re.match(pattern, '2026-02-10')
# m.group('year') = '2026'
# m.group('month') = '02'
# m.group('day') = '10'非キャプチャグループ
キャプチャ不要な場合は(?:...)を使用します。
// Non-capturing group
const regex = /(?:https?|ftp):\/\/[^\s]+/;
// Groups the protocol options without capturing them
// Only the full URL is in match[0]選択(OR)
パイプ|で複数の選択肢をマッチします。
// Alternation examples
/cat|dog/ // Match "cat" or "dog"
/(red|blue) car/ // Match "red car" or "blue car"
/^(GET|POST|PUT|DELETE)\s/ // Match HTTP methods先読みと後読み(ゼロ幅アサーション)
先読み/後読みは現在位置の前後にパターンが存在するかを文字を消費せずに確認します。
| Syntax | Type | Description |
|---|---|---|
(?=...) | Positive lookahead | What follows must match |
(?!...) | Negative lookahead | What follows must NOT match |
(?<=...) | Positive lookbehind | What precedes must match |
(?<!...) | Negative lookbehind | What precedes must NOT match |
肯定先読み (?=...)
指定パターンが後に続く位置にマッチ。
// Match a number followed by "px"
/\d+(?=px)/
// "20px 30em 40px" → matches "20" and "40" (not "30")
// Password: must contain at least one digit
/^(?=.*\d).{8,}$/否定先読み (?!...)
指定パターンが後に続かない位置にマッチ。
// Match "cat" NOT followed by "fish"
/cat(?!fish)/
// "catfish catdog" → matches "cat" in "catdog" only
// Match numbers NOT followed by a unit
/\d+(?!\s*(px|em|rem|%))/肯定後読み (?<=...)
指定パターンが前にある位置にマッチ。
// Match a number preceded by "$"
/(?<=\$)\d+(\.\d{2})?/
// "$49.99 and €29.99" → matches "49.99" only
// Extract value after "price:"
/(?<=price:\s*)\d+/否定後読み (?<!...)
指定パターンが前にない位置にマッチ。
// Match "cat" NOT preceded by "wild"
/(?<!wild)cat/
// "wildcat housecat" → matches "cat" in "housecat" only
// Match digits not preceded by a minus sign
/(?<!-)\b\d+\b/注意:後読みは一部のエンジンでサポートが限定的です。GoのRE2エンジンは先読み/後読みをサポートしません。
Regexフラグ(修飾子)
フラグはregexエンジンのパターン解釈方法を変更します。
| Flag | Name | Description | Example |
|---|---|---|---|
g | Global | Find all matches, not just the first | /cat/g finds all "cat" occurrences |
i | Case-insensitive | Match upper and lowercase interchangeably | /hello/i matches "Hello", "HELLO" |
m | Multiline | ^ and $ match line starts/ends | /^start/m matches at each line start |
s | Dotall (Single-line) | . matches newline characters too | /a.b/s matches "a\nb" |
u | Unicode | Enable full Unicode matching | /\u{1F600}/u matches emoji |
y | Sticky | Match only at lastIndex position | Used for tokenizing / lexing |
// Combining flags
const regex = /^hello world$/gim;
// In Python, flags are constants:
import re
pattern = re.compile(r'^hello world$', re.IGNORECASE | re.MULTILINE)
// In Go, use inline flags:
// (?i) for case-insensitive, (?m) for multiline, (?s) for dotall
regexp.MustCompile("(?im)^hello world$")一般的なパターン早見表
最もよく使われるregexパターンの一覧です。
| Use Case | Pattern |
|---|---|
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ | |
| URL (HTTP/S) | ^https?:\/\/[^\s]+$ |
| IPv4 Address | ^((25[0-5]|(2[0-4]|1\d|[1-9]|)\d)\.?\b){4}$ |
| Date (YYYY-MM-DD) | ^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])$ |
| Time (HH:MM:SS) | ^([01]\d|2[0-3]):[0-5]\d:[0-5]\d$ |
| Hex Color | ^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$ |
| Strong Password | ^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&]).{8,}$ |
| Phone (E.164) | ^\+[1-9]\d{1,14}$ |
| UUID | ^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$ |
| Semantic Version | ^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-[\w.]+)?(\+[\w.]+)?$ |
| HTML Tag | <([a-zA-Z][a-zA-Z0-9]*)\b[^>]*>(.*?)<\/\1> |
| Trim Whitespace | ^\s+|\s+$ |
各プログラミング言語でのRegex
構文は概ね共通ですが、各言語に固有のAPIがあります。
JavaScript
// Creating regex in JavaScript
const regex1 = /^\d+$/; // Literal syntax
const regex2 = new RegExp('^\\d+$'); // Constructor (needs double-escape)
// Testing
regex1.test('12345'); // true
// Matching
'hello world'.match(/\w+/g); // ['hello', 'world']
// Replacing
'2026-02-10'.replace(
/^(\d{4})-(\d{2})-(\d{2})$/,
'$2/$3/$1'
); // '02/10/2026'
// matchAll (ES2020) - get all matches with groups
const text = 'Price: $10, Tax: $2';
for (const m of text.matchAll(/\$(\d+)/g)) {
console.log(m[0], m[1]);
// '$10' '10', then '$2' '2'
}
// Named groups (ES2018+)
const { groups } = '2026-02-10'.match(
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
);
console.log(groups.year); // '2026'Python
import re
# Compile for reuse (recommended)
pattern = re.compile(r'^\d+$')
# Test if the entire string matches
pattern.match('12345') # Match object (truthy)
pattern.match('abc') # None (falsy)
# Search anywhere in the string
re.search(r'\d+', 'abc 123 def') # Finds '123'
# Find all matches
re.findall(r'\w+', 'hello world') # ['hello', 'world']
# Replace
re.sub(
r'^(\d{4})-(\d{2})-(\d{2})$',
r'\2/\3/\1',
'2026-02-10'
) # '02/10/2026'
# Named groups
m = re.match(
r'(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})',
'2026-02-10'
)
m.group('year') # '2026'
m.group('month') # '02'
# Flags
re.findall(r'^start', text, re.MULTILINE | re.IGNORECASE)
# Split by pattern
re.split(r'[,;\s]+', 'a, b; c d') # ['a', 'b', 'c', 'd']Go (Golang)
package main
import (
"fmt"
"regexp"
)
func main() {
// Compile (panics on invalid pattern)
re := regexp.MustCompile(`^\d+$`)
// Test
fmt.Println(re.MatchString("12345")) // true
fmt.Println(re.MatchString("abc")) // false
// Find first match
re2 := regexp.MustCompile(`\d+`)
fmt.Println(re2.FindString("abc 123 def")) // "123"
// Find all matches
fmt.Println(re2.FindAllString("10 cats and 20 dogs", -1))
// ["10", "20"]
// Replace
re3 := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)
result := re3.ReplaceAllString("2026-02-10", "$2/$3/$1")
fmt.Println(result) // "02/10/2026"
// Named groups
re4 := regexp.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`)
match := re4.FindStringSubmatch("2026-02-10")
for i, name := range re4.SubexpNames() {
if name != "" {
fmt.Printf("%s: %s\n", name, match[i])
}
}
// year: 2026, month: 02, day: 10
// Inline flags: (?i) case-insensitive, (?m) multiline, (?s) dotall
re5 := regexp.MustCompile(`(?i)hello`)
fmt.Println(re5.MatchString("HELLO")) // true
}GoはRE2エンジンを使用し、先読み、後読み、後方参照をサポートしません。
パフォーマンスのヒントとベストプラクティス
具体的に:.の代わりに[a-zA-Z]を使用。
壊滅的バックトラッキングを避ける:(a+)+のようなネストした量指定子を避ける。
// BAD: Catastrophic backtracking risk
const bad = /^(a+)+$/;
bad.test('aaaaaaaaaaaaaaaaaaaaa!'); // Extremely slow!
// GOOD: Flatten nested quantifiers
const good = /^a+$/;
good.test('aaaaaaaaaaaaaaaaaaaaa!'); // Instant: false非キャプチャグループを使う:キャプチャ不要なら(?:...)を使用。
一度コンパイル:PythonやGoではコンパイル済みオブジェクトを再利用。
# Python: compile once, reuse many times
import re
email_re = re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
# Fast: uses pre-compiled pattern
for addr in addresses:
if email_re.match(addr):
print(f"Valid: {addr}")段階的にテスト:複雑なパターンはステップバイステップで構築。
よくある質問
正規表現チートシートとは何ですか?なぜ必要ですか?
構文、メタ文字、量指定子、フラグ、一般的なパターンを一か所にまとめたクイックリファレンスです。経験豊富な開発者でもすべてを暗記することはできません。
regexの .* と .*? の違いは何ですか?
.*は貪欲(最長マッチ)、.*?は控えめ(最短マッチ)。最初の区切り文字で止めたい場合は控えめを使います。
すべてのプログラミング言語で同じregex構文が使えますか?
ほとんどがPCREをサポートしますが、高度な機能は異なります。JavaScriptはES2018で後読みを追加、Go(RE2)は後読みをサポートしません。
regexパターンのテストとデバッグ方法は?
リアルタイムでマッチを表示するインタラクティブなRegexテスターを使用してください。パターンを段階的に構築しましょう。
壊滅的バックトラッキングとは?
regexエンジンが文字列の不一致を判断するのに指数的な時間がかかる現象です。ネストした量指定子を避け、文字クラスを具体的にしましょう。