Regex kiểm tra email, URL và số điện thoại
Regex kiểm tra dữ liệu được sao chép nhiều hơn bất kỳ loại nào khác, và phần lớn trong số đó sai một cách tinh vi. Dưới đây là các mẫu hoạt động tốt trong form thực tế, mỗi phần làm gì, và những trường hợp regex không phải công cụ phù hợp.
Kiểm tra lỏng, xác minh thật
Regex chỉ cho bạn biết một đầu vào trông giống địa chỉ email; chỉ khi gửi thư đi thì mới chứng minh được nó tồn tại. Các mẫu quá chặt sẽ từ chối người dùng thật — dấu cộng, tên miền dài, tên quốc tế — nhưng vẫn để lọt lỗi gõ sai. Hãy chọn mẫu bắt được các lỗi rõ ràng, rồi xác minh thêm.
Địa chỉ email
Một mẫu thực dụng khớp với hầu hết địa chỉ email thật:
^[^\s@]+@[^\s@]+\.[^\s@]{2,}$
Gồm phần tên, một @, tên miền có dấu chấm và không có khoảng trắng. Mẫu này chấp nhận ada+news@example.co.uk và từ chối ada@example cùng ada @example.com. Một phiên bản chặt hơn cho phần tên:
^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$
Mẫu này từ chối địa chỉ có ký tự quốc tế (như josé@example.com), nên hãy ưu tiên mẫu đầu tiên nếu người dùng của bạn ở khắp thế giới. Trong HTML, <input type="email"> đã tự kiểm tra theo quy tắc riêng của trình duyệt. Để kiểm tra một tên miền có thực sự nhận được thư hay không, hãy tra cứu bản ghi MX bằng Email DNS Checker.
URL
Đừng viết regex cho URL — hãy phân tích cú pháp bằng parser. Mọi môi trường chạy hiện đại đều có bộ phân tích URL hiểu đúng các quy tắc:
function isHttpUrl(value) {
try {
const u = new URL(value);
return u.protocol === 'http:' || u.protocol === 'https:';
} catch {
return false;
}
}
Kiểm tra giao thức rất quan trọng: new URL('javascript:alert(1)') vẫn phân tích thành công, và chuỗi đó tuyệt đối không được đưa vào href. Nếu bạn cần regex để tìm URL trong văn bản, hãy dùng mẫu đơn giản rồi phân tích từng kết quả khớp:
https?:\/\/[^\s<>"']+
Tách URL thành giao thức, host, đường dẫn và tham số truy vấn bằng URL Parser.
Số điện thoại
Định dạng số điện thoại khác nhau theo từng quốc gia, nên regex an toàn nhất chỉ nên làm sạch đầu vào. Loại bỏ mọi thứ ngoại trừ chữ số và dấu cộng ở đầu, rồi kiểm tra độ dài theo chuẩn E.164 (tối đa 15 chữ số):
const clean = input.replace(/(?!^\+)[^\d]/g, '');
const ok = /^\+?[1-9]\d{6,14}$/.test(clean);
Để kiểm tra thật sự theo từng quốc gia — mã vùng, di động hay cố định — hãy dùng thư viện như libphonenumber. Nếu bạn chỉ chấp nhận số Bắc Mỹ, có thể dùng mẫu sau:
^\(?([2-9]\d{2})\)?[-.\s]?(\d{3})[-.\s]?(\d{4})$
Kiểm tra trước khi triển khai
Dán mẫu vào Regex Tester cùng danh sách mẫu hợp lệ và không hợp lệ, mỗi dòng một mẫu, rồi bật cờ multiline để ^ và $ khớp với từng dòng. Nếu một mẫu bạn thừa hưởng từ người khác khó đọc, Regex Explainer sẽ giải thích từng token. Hãy cẩn thận với catastrophic backtracking: các lượng từ lồng nhau như (a+)+ có thể làm treo máy chủ khi gặp đầu vào được thiết kế sẵn.