Category: reference
Regular Expressions ใน JavaScript — Pattern Matching ที่ใช้ได้จริง
Regex patterns ที่ใช้บ่อยใน JavaScript และ TypeScript รวม flags, character classes, groups, lookahead/lookbehind และ use cases จริงสำหรับ validation และ parsing
สารบัญ
Syntax พื้นฐาน
// สร้าง regex
const pattern1 = /hello/; // literal
const pattern2 = new RegExp('hello'); // constructor (ใช้เมื่อ dynamic)
// methods
pattern1.test('hello world'); // true — ทดสอบว่า match หรือไม่
'hello world'.match(/hello/); // ['hello'] — หา match แรก
'hello world'.replace(/hello/, 'hi'); // 'hi world'
'a,b,,c'.split(/,+/); // ['a', 'b', 'c'] — split ด้วย pattern
Flags
/pattern/i // case-insensitive — ไม่สนใจตัวพิมพ์เล็ก/ใหญ่
/pattern/g // global — หาทุก match ไม่ใช่แค่อันแรก
/pattern/m // multiline — ^ และ $ match ต่อบรรทัด
/pattern/s // dotAll — . match newline ด้วย
/pattern/gi // รวมหลาย flag
'Hello WORLD'.match(/[a-z]+/gi); // ['Hello', 'WORLD']
Character Classes
\d // digit: [0-9]
\D // ไม่ใช่ digit
\w // word: [a-zA-Z0-9_]
\W // ไม่ใช่ word
\s // whitespace (space, tab, newline)
\S // ไม่ใช่ whitespace
. // อักขระใดก็ได้ยกเว้น newline
[abc] // a หรือ b หรือ c
[^abc] // ไม่ใช่ a, b, c
[a-z] // a ถึง z
[a-zA-Z] // ตัวอักษร English ใดก็ได้
Quantifiers
a* // 0 ครั้งหรือมากกว่า (greedy)
a+ // 1 ครั้งหรือมากกว่า
a? // 0 หรือ 1 ครั้ง (optional)
a{3} // ตรงๆ 3 ครั้ง
a{2,4} // 2 ถึง 4 ครั้ง
a{2,} // 2 ครั้งขึ้นไป
// Non-greedy (lazy) — จับน้อยที่สุด
a*? // 0 ครั้งหรือมากกว่า แต่จับน้อยที่สุด
a+? // 1 ครั้งหรือมากกว่า แต่จับน้อยที่สุด
Groups และ Capturing
// Capturing group — จับ match ใว้
const match = '2026-06-14'.match(/(\d{4})-(\d{2})-(\d{2})/);
// match[0] = '2026-06-14' (full match)
// match[1] = '2026'
// match[2] = '06'
// match[3] = '14'
// Named capturing group
const { year, month, day } = '2026-06-14'.match(
/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/
)?.groups ?? {};
// Non-capturing group — จัดกลุ่มแต่ไม่จับ
/(https?):\/\//.test('https://example.com'); // http: หรือ https:
Lookahead และ Lookbehind
// Positive lookahead — X ตามด้วย Y
/\d+(?= baht)/g // จับตัวเลขที่ตามด้วย " baht"
'100 baht 200 usd'.match(/\d+(?= baht)/g); // ['100']
// Negative lookahead — X ที่ไม่ตามด้วย Y
/\d+(?! baht)/g // จับตัวเลขที่ไม่ตามด้วย " baht"
// Positive lookbehind — X ที่นำหน้าด้วย Y
/(?<=฿)\d+/g // จับตัวเลขที่นำหน้าด้วย ฿
'฿100 $200'.match(/(?<=฿)\d+/g); // ['100']
Use Cases จริง
// Email validation (basic)
function isValidEmail(email: string): boolean {
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
// Thai phone number
function isThaiPhone(phone: string): boolean {
return /^(0[689]\d{8}|0[2-7]\d{7})$/.test(phone.replace(/[-\s]/g, ''));
}
// URL slug — lowercase, hyphens เท่านั้น
function slugify(text: string): string {
return text
.toLowerCase()
.replace(/[^\w\s-]/g, '') // ลบ special chars
.replace(/[\s_-]+/g, '-') // เปลี่ยน spaces/underscores เป็น -
.replace(/^-+|-+$/g, ''); // ลบ leading/trailing -
}
// Extract all URLs จาก text
function extractUrls(text: string): string[] {
return text.match(/https?:\/\/[^\s)>"]+/g) ?? [];
}
// Strip HTML tags
function stripHtml(html: string): string {
return html.replace(/<[^>]+>/g, '');
}
// Word count — นับคำ (ไม่รวม whitespace ต่อเนื่อง)
function countWords(text: string): number {
return text.trim().split(/\s+/).filter(Boolean).length;
}
TypeScript กับ Regex
// RegExp type
const pattern: RegExp = /\d+/g;
// ใช้กับ matchAll สำหรับ global flag
const text = 'foo 1 bar 2 baz 3';
const matches = [...text.matchAll(/(\d+)/g)];
// matches = [['1', '1'], ['2', '2'], ['3', '3']]
// แต่ละ element เป็น array ที่มี full match และ groups
// String.prototype.replaceAll() — ง่ายกว่า /g flag ในบางกรณี
'a-b-c'.replaceAll('-', '_'); // 'a_b_c'
// Named groups กับ TypeScript (ต้อง match ก่อน)
const result = /(?<year>\d{4})/.exec('2026');
const year = result?.groups?.year; // string | undefined
ข้อควรระวัง
// ❌ Catastrophic Backtracking — regex ที่ทำให้ hang
// /^(a+)+$/ กับ input 'aaaaaab' — exponential time
// ❌ อย่าใช้ regex ที่ซ้อน quantifier แบบนี้
// ❌ RegExp constructor กับ user input
const userInput = '.+'; // user input ที่ไม่ผ่าน sanitize
new RegExp(userInput); // ทำงานได้ แต่เสี่ยง ReDoS attack
// ✅ escape user input ก่อนนำเข้า RegExp
function escapeRegex(str: string): string {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
const safe = new RegExp(escapeRegex(userInput));