Regular expression มีชื่อเสียงว่าดูเหมือนเสียงรบกวนแบบสุ่ม Pattern อย่าง ^[\w.-]+@[\w-]+\.\w{2,}$ อาจรู้สึกเหมือนแมวเดินผ่านคีย์บอร์ด แต่เบื้องหลังไวยากรณ์ที่ลึกลับนี้คือแนวคิดที่สวยงามอย่างน่าทึ่ง: ภาษากระชับสำหรับอธิบาย pattern ในข้อความ
ไม่ว่าคุณจะกำลัง validate input ฟอร์ม, ค้นหาไฟล์ log, ทำความสะอาดข้อมูล หรือทำ find-and-replace ทั่ว codebase, regex เป็นหนึ่งในเครื่องมือที่อเนกประสงค์ที่สุดในชุดเครื่องมือของนักพัฒนา และคุณไม่ต้องจำทุกฟีเจอร์ที่คลุมเครือเพื่อให้ได้ประโยชน์จริง ๆ ส่วนประกอบพื้นฐานไม่กี่อย่างครอบคลุมกรณีการใช้งานเชิงปฏิบัติส่วนใหญ่
Regex ทำอะไรจริง ๆ
Regular expression (regex หรือ regexp) คือ pattern ที่อธิบายชุดของสตริง คุณส่งมันให้กลไกค้นหา — ในภาษาโปรแกรม โปรแกรมแก้ไขข้อความ หรือเครื่องมือบรรทัดคำสั่ง — แล้วมันจะหาทุกสตริงที่ตรงกัน
ลองคิดว่ามันเป็น search query ที่อัพเกรดแล้ว:
- ค้นหาปกติ: หาคำว่า "error" ตามตัวอักษร
- ค้นหา Regex: หาอะไรก็ได้ที่ดูเหมือน IP address, วันที่, ที่อยู่อีเมล หรือโครงสร้างใด ๆ ที่คุณอธิบายได้
Regex ถูกประดิษฐ์โดยนักคณิตศาสตร์ Stephen Kleene ในปี 1956 และเข้าสู่คอมพิวเตอร์ผ่าน Unix text editor ในทศวรรษ 1960 ปัจจุบันรองรับในแทบทุกภาษาโปรแกรมและ text editor
ส่วนประกอบพื้นฐาน
อักขระตามตัวอักษร
Regex ที่ง่ายที่สุดคือข้อความธรรมดา Pattern hello ตรงกับสตริง "hello" ทุกที่ที่ปรากฏ ไม่มีอะไรซับซ้อน
จุด (.) — อักขระใด ๆ
จุดตรงกับอักขระเดียวใด ๆ ยกเว้น newline
h.tตรงกับ "hat", "hit", "hot", "h3t" และแม้แต่ "h t"
Character class ([])
วงเล็บเหลี่ยมกำหนดชุดอักขระที่อนุญาตในตำแหน่งเดียว
[aeiou]— สระใด ๆ[0-9]— ตัวเลขใด ๆ[A-Za-z]— ตัวอักษรใด ๆ[^0-9]— อักขระใด ๆ ที่ไม่ใช่ตัวเลข (^ในวงเล็บหมายถึง "ไม่ใช่")
Shorthand class
| Shorthand | ความหมาย | เทียบเท่า |
|---|---|---|
\d |
ตัวเลขใด ๆ | [0-9] |
\w |
อักขระคำ | [A-Za-z0-9_] |
\s |
Whitespace | [ \t\n\r] |
\D |
ไม่ใช่ตัวเลข | [^0-9] |
\W |
ไม่ใช่อักขระคำ | [^A-Za-z0-9_] |
\S |
ไม่ใช่ whitespace | [^ \t\n\r] |
Quantifier — จำนวนเท่าไหร่
Quantifier ควบคุมว่าองค์ประกอบก่อนหน้าต้องปรากฏกี่ครั้ง
| สัญลักษณ์ | ความหมาย | ตัวอย่าง | ตรงกับ |
|---|---|---|---|
* |
ศูนย์หรือมากกว่า | ab*c |
"ac", "abc", "abbc" |
+ |
หนึ่งหรือมากกว่า | ab+c |
"abc", "abbc" (ไม่ใช่ "ac") |
? |
ศูนย์หรือหนึ่ง | colou?r |
"color" และ "colour" |
{3} |
ตรง 3 | \d{3} |
"123", "456" |
{2,4} |
ระหว่าง 2 ถึง 4 | \d{2,4} |
"12", "123", "1234" |
Anchor — ตำแหน่ง
^— ต้นสตริง (หรือบรรทัด ด้วย flagm)$— ท้ายสตริง (หรือบรรทัด)\b— ขอบเขตคำ
Pattern ^\d{4}$ ตรงกับสตริงที่เป็นตัวเลขสี่ตัวพอดี เช่น "2026" แต่ไม่ใช่ "abc2026" หรือ "2026xyz"
Group และ alternation
(abc)— จับ "abc" เป็นกลุ่มa|b— ตรงกับ "a" หรือ "b"(cat|dog)— ตรงกับ "cat" หรือ "dog"
Group ยังให้คุณใช้ quantifier กับลำดับ: (ha)+ ตรงกับ "ha", "haha", "hahaha"
Pattern เชิงปฏิบัติที่พบบ่อย
Validate อีเมล (พื้นฐาน)
^[\w.-]+@[\w-]+\.\w{2,}$
ตรงกับ user@example.com, first.last@company.co.uk (บางส่วน) และปฏิเสธสตริงที่ไม่มี @ หรือโดเมน
สำคัญ: การ validate ที่อยู่อีเมลอย่างสมบูรณ์แบบด้วย regex นั้นยากอย่างเลื่องชื่อ — ข้อกำหนด RFC 5322 เต็มรูปแบบนั้นซับซ้อนมาก สำหรับระบบ production ใช้ regex พื้นฐานสำหรับตรวจสอบรูปแบบ แล้วตรวจสอบที่อยู่โดยส่งอีเมลยืนยัน
จับคู่เบอร์โทรศัพท์
\+?\d{1,3}[-.\s]?\(?\d{1,4}\)?[-.\s]?\d{3,4}[-.\s]?\d{3,4}
รองรับรูปแบบเช่น +1 555 123 4567, 555-123-4567 และ (555) 123-4567
จับคู่ URL
https?://[\w.-]+(/[\w./?&=-]*)?
ตรงกับ https://example.com, http://example.com/path?q=hello
จับคู่วันที่ (YYYY-MM-DD)
\d{4}-\d{2}-\d{2}
ตรงกับ 2026-03-29, 1999-12-31 หมายเหตุ: ตรวจสอบแค่รูปแบบ ไม่ใช่ความถูกต้อง — มันจะจับคู่ 9999-99-99 ด้วย
Flag ที่เปลี่ยนพฤติกรรม
กลไก regex ส่วนใหญ่รองรับ flag ที่ปรับเปลี่ยนวิธีใช้ pattern:
| Flag | ชื่อ | ผล |
|---|---|---|
g |
Global | หาทุกที่ที่ตรงกัน ไม่ใช่แค่ที่แรก |
i |
Case-insensitive | hello ตรงกับ "Hello", "HELLO" ฯลฯ |
m |
Multiline | ^ และ $ ตรงกับต้น/ท้ายของแต่ละบรรทัด |
s |
Dotall | . ตรงกับอักขระ newline ด้วย |
ใน JavaScript, flag ต่อท้ายหลัง slash ปิด: /hello/gi ใน Python, ส่งเป็น argument: re.findall(r"hello", text, re.IGNORECASE)
เมื่อไหร่ที่ Regex มากเกินไป
Regex มีพลัง แต่ไม่ใช่เครื่องมือที่ถูกต้องเสมอ:
- Parse HTML หรือ XML ใช้ DOM parser ที่เหมาะสม Regex ไม่สามารถจัดการ tag ที่ซ้อนกันได้อย่างน่าเชื่อถือ
- Parse JSON ใช้
JSON.parse()หรือเทียบเท่า Regex จะพังกับกรณีพิเศษ - Validation ที่ซับซ้อน ถ้า pattern ของคุณกินพื้นที่หลายบรรทัดและอ่านใช้เวลาห้านาที ลองเขียน validation code แบบ procedural แทน
- การดำเนินการ string แบบง่าย ถ้าคุณแค่ต้องการ
startsWith(),includes()หรือsplit(), string method ธรรมดาชัดเจนกว่าและเร็วกว่า
ข้อผิดพลาดที่พบบ่อย
- ลืม escape อักขระพิเศษ จุด
.ตรงกับอักขระใด ๆ ถ้าจะจับคู่จุดจริง ๆ ใช้\.เหมือนกันสำหรับ(,),[,],+,*,?,{,},^,$,|และ\ - Greedy กับ lazy matching ตามค่าเริ่มต้น
.*เป็น greedy — จับคู่มากที่สุด เพิ่ม?เพื่อทำให้ lazy:.*?จับคู่น้อยที่สุด สิ่งนี้สำคัญเมื่อดึงเนื้อหาระหว่างตัวคั่น - Catastrophic backtracking Quantifier ที่ซ้อนกันเช่น
(a+)+อาจทำให้กลไกลอง path แบบ exponential กับ input บางตัว ทำให้โปรแกรมค้าง หลีกเลี่ยงการซ้ำซ้อนที่ซ้อนกันบน pattern ที่ทับซ้อนกัน - ลืม anchor ถ้าไม่มี
^และ$, pattern ของคุณจับคู่ substring\d{3}จับคู่ "123" ใน "abc12345" ใช้^\d{3}$ถ้าต้องการจับคู่ที่แม่นยำ
เรียนรู้เพิ่มเติม
วิธีที่ดีที่สุดในการเรียนรู้ regex คือทดลอง พิมพ์ pattern วาง test text แล้วดูว่าอะไรถูกเน้น ปรับและทำซ้ำจนกว่าจะเข้าใจว่าแต่ละส่วนทำงานอย่างไร
- วิธีทดสอบ Regex Pattern — บทช่วยสอนแบบโต้ตอบพร้อมตัวอย่าง
- Regex Tester — วาง pattern และ test data ของคุณ ดู match ที่เน้นแบบ real-time
