Regular expression có tiếng là trông giống như tiếng ồn ngẫu nhiên. Một mẫu như ^[\w.-]+@[\w-]+\.\w{2,}$ có thể khiến bạn cảm giác như mèo đi ngang qua bàn phím. Nhưng đằng sau cú pháp khó hiểu là một ý tưởng cực kỳ thanh lịch: một ngôn ngữ ngắn gọn để mô tả các mẫu trong văn bản.
Dù bạn đang xác thực đầu vào biểu mẫu, tìm kiếm tệp nhật ký, dọn dẹp dữ liệu, hay thực hiện tìm và thay thế trên toàn bộ mã nguồn, regex là một trong những công cụ đa năng nhất trong bộ công cụ của lập trình viên. Và bạn không cần ghi nhớ mọi tính năng ít gặp để đạt được giá trị thực sự. Một số ít khối xây dựng cơ bản đã bao phủ phần lớn các trường hợp sử dụng thực tế.
Regex thực sự làm gì
Regular expression (regex hoặc regexp) là một mẫu mô tả một tập hợp chuỗi. Bạn cung cấp nó cho công cụ tìm kiếm — trong ngôn ngữ lập trình, trình soạn thảo văn bản, hoặc công cụ dòng lệnh — và nó tìm mọi chuỗi khớp.
Hãy coi nó như truy vấn tìm kiếm nâng cấp:
- Tìm kiếm thông thường: tìm chính xác từ "error"
- Tìm kiếm regex: tìm bất kỳ thứ gì trông giống địa chỉ IP, ngày tháng, địa chỉ email, hoặc bất kỳ cấu trúc nào bạn có thể mô tả
Regex được phát minh bởi nhà toán học Stephen Kleene vào năm 1956 và bước vào lĩnh vực tin học thông qua các trình soạn thảo văn bản Unix vào những năm 1960. Ngày nay nó được hỗ trợ trong hầu hết mọi ngôn ngữ lập trình và trình soạn thảo văn bản.
Các khối xây dựng
Ký tự chữ
Regex đơn giản nhất là văn bản thuần. Mẫu hello khớp với chuỗi "hello" ở bất cứ đâu nó xuất hiện. Không có gì đặc biệt.
Dấu chấm (.) — bất kỳ ký tự nào
Dấu chấm khớp với bất kỳ ký tự đơn nào trừ ký tự xuống dòng.
h.tkhớp với "hat", "hit", "hot", "h3t", và thậm chí "h t"
Lớp ký tự ([])
Ngoặc vuông xác định tập hợp ký tự được phép tại một vị trí.
[aeiou]— bất kỳ nguyên âm nào[0-9]— bất kỳ chữ số nào[A-Za-z]— bất kỳ chữ cái nào[^0-9]— bất kỳ ký tự nào KHÔNG phải chữ số (dấu^bên trong ngoặc vuông nghĩa là "không")
Lớp viết tắt
| Viết tắt | Ý nghĩa | Tương đương |
|---|---|---|
\d |
Bất kỳ chữ số | [0-9] |
\w |
Ký tự từ | [A-Za-z0-9_] |
\s |
Khoảng trắng | [ \t\n\r] |
\D |
Không phải chữ số | [^0-9] |
\W |
Không phải ký tự từ | [^A-Za-z0-9_] |
\S |
Không phải khoảng trắng | [^ \t\n\r] |
Bộ định lượng — bao nhiêu
Bộ định lượng kiểm soát số lần phần tử trước đó phải xuất hiện.
| Ký hiệu | Ý nghĩa | Ví dụ | Khớp với |
|---|---|---|---|
* |
Không hoặc nhiều | ab*c |
"ac", "abc", "abbc" |
+ |
Một hoặc nhiều | ab+c |
"abc", "abbc" (không phải "ac") |
? |
Không hoặc một | colou?r |
"color" và "colour" |
{3} |
Chính xác 3 | \d{3} |
"123", "456" |
{2,4} |
Từ 2 đến 4 | \d{2,4} |
"12", "123", "1234" |
Neo — vị trí
^— đầu chuỗi (hoặc dòng, với cờm)$— cuối chuỗi (hoặc dòng)\b— ranh giới từ
Mẫu ^\d{4}$ khớp với chuỗi chính xác bốn chữ số, như "2026", nhưng không phải "abc2026" hay "2026xyz".
Nhóm và phép thay thế
(abc)— bắt "abc" thành một nhóma|b— khớp "a" hoặc "b"(cat|dog)— khớp "cat" hoặc "dog"
Nhóm cũng cho phép bạn áp dụng bộ định lượng cho chuỗi: (ha)+ khớp "ha", "haha", "hahaha".
Các mẫu thực tế phổ biến
Xác thực email (cơ bản)
^[\w.-]+@[\w-]+\.\w{2,}$
Mẫu này khớp user@example.com, first.last@company.co.uk (một phần), và từ chối các chuỗi không có @ hoặc tên miền.
Quan trọng: Xác thực hoàn hảo địa chỉ email bằng regex nổi tiếng là khó — đặc tả đầy đủ RFC 5322 cực kỳ phức tạp. Với hệ thống sản xuất, hãy dùng regex cơ bản để kiểm tra định dạng và sau đó xác minh địa chỉ bằng cách gửi email xác nhận.
Khớp số điện thoại
\+?\d{1,3}[-.\s]?\(?\d{1,4}\)?[-.\s]?\d{3,4}[-.\s]?\d{3,4}
Mẫu này xử lý các định dạng như +1 555 123 4567, 555-123-4567, và (555) 123-4567.
Khớp URL
https?://[\w.-]+(/[\w./?&=-]*)?
Khớp https://example.com, http://example.com/path?q=hello.
Khớp ngày (YYYY-MM-DD)
\d{4}-\d{2}-\d{2}
Khớp 2026-03-29, 1999-12-31. Lưu ý: mẫu này chỉ kiểm tra định dạng, không kiểm tra tính hợp lệ — nó cũng khớp 9999-99-99.
Cờ thay đổi hành vi
Hầu hết các engine regex hỗ trợ cờ điều chỉnh cách mẫu được áp dụng:
| Cờ | Tên | Hiệu ứng |
|---|---|---|
g |
Toàn cục | Tìm tất cả kết quả, không chỉ kết quả đầu tiên |
i |
Không phân biệt hoa thường | hello khớp "Hello", "HELLO", v.v. |
m |
Nhiều dòng | ^ và $ khớp đầu/cuối mỗi dòng |
s |
Dotall | . cũng khớp ký tự xuống dòng |
Trong JavaScript, cờ được thêm sau dấu gạch chéo đóng: /hello/gi. Trong Python, chúng được truyền dưới dạng đối số: re.findall(r"hello", text, re.IGNORECASE).
Khi nào regex là quá mức
Regex mạnh mẽ, nhưng không phải lúc nào cũng là công cụ đúng:
- Phân tích HTML hoặc XML. Dùng parser DOM chuyên dụng. Regex không thể xử lý đáng tin cậy các thẻ lồng nhau.
- Phân tích JSON. Dùng
JSON.parse()hoặc tương đương. Regex sẽ lỗi ở các trường hợp đặc biệt. - Xác thực phức tạp. Nếu mẫu của bạn kéo dài nhiều dòng và mất năm phút để đọc, hãy cân nhắc viết mã xác thực tuần tự thay thế.
- Thao tác chuỗi đơn giản. Nếu bạn chỉ cần
startsWith(),includes(), hoặcsplit(), các phương thức chuỗi thuần rõ ràng và nhanh hơn.
Bẫy thường gặp
- Quên thoát ký tự đặc biệt. Dấu chấm
.khớp bất kỳ ký tự nào. Để khớp dấu chấm thật, dùng\.. Tương tự cho(,),[,],+,*,?,{,},^,$,|, và\. - Khớp tham lam vs lười. Mặc định,
.*là tham lam — nó khớp nhiều nhất có thể. Thêm?để làm cho nó lười:.*?khớp ít nhất có thể. Điều này quan trọng khi trích xuất nội dung giữa các dấu phân cách. - Quay lui thảm họa. Bộ định lượng lồng nhau như
(a+)+có thể khiến engine thử số lượng đường đi theo cấp số nhân trên một số đầu vào, đóng băng chương trình. Tránh lặp lồng nhau trên các mẫu chồng lấp. - Quên neo. Không có
^và$, mẫu của bạn khớp chuỗi con.\d{3}khớp "123" bên trong "abc12345". Dùng^\d{3}$nếu bạn cần khớp chính xác.
Tìm hiểu thêm
Cách tốt nhất để học regex là thử nghiệm. Gõ một mẫu, dán một số văn bản thử nghiệm, và xem phần nào sáng lên. Điều chỉnh và lặp lại cho đến khi bạn hiểu cách từng phần hoạt động.
- Cách kiểm tra mẫu Regex — hướng dẫn tương tác với ví dụ
- Trình kiểm tra Regex — dán mẫu và dữ liệu thử nghiệm, xem kết quả khớp được tô sáng theo thời gian thực
