03 / HƯỚNG DẪN
Quy trình an toàn để test biểu thức chính quy
Vòng viết-test-refactor cho biểu thức chính quy JavaScript: dữ liệu mẫu thực tế, vệ sinh catastrophic backtracking, kỷ luật neo chuỗi, ngữ nghĩa flag, và vì sao test trong trình duyệt giữ pattern riêng tư.
Vòng lặp: viết, test, refactor
Regex đáng tin không bao giờ viết xong trong một lần. Bắt đầu với pattern nhỏ nhất khớp một ví dụ thật, chạy nó, rồi nới hoặc siết dựa trên ví dụ tiếp theo. Văn bản mẫu là đặc tả; pattern là hiện thực.
Khi bật chạy tự động, công cụ đánh giá sau một khoảng dừng ngắn lúc nhập, thay vì chạy theo từng phím. Vòng lặp sửa rồi thử vẫn nhanh.
- Bắt đầu từ mẫuViết pattern dựa trên mẫu cụ thể, không viết từ trí nhớ: dán một dòng thật của log hay tài liệu bạn định parse.
- Test mỗi lần sửaTest sau mỗi thay đổi — regex không có cảnh báo biên dịch, nên phản hồi duy nhất là nó khớp gì và bỏ sót gì.
- Refactor cho người đọcRefactor cho người đọc khi đã qua: nhóm bắt có tên và nhóm không bắt làm pattern đang chạy sống sót được với người đọc kế tiếp.
Tôn trọng catastrophic backtracking
Engine regex của JavaScript quay lui: khi khớp thất bại, nó thử lại với độ dài khác cho từng quantifier. Quantifier lồng nhau như (a+)+ trên chuỗi suýt khớp làm số lần thử bùng nổ theo hàm mũ — pattern trả lời tức thì với dữ liệu tốt có thể chạy hàng năm với dữ liệu xấu. Kẻ tấn công gọi đây là ReDoS.
JavaScript Regex Tester chạy mẫu trong Web Worker với giới hạn 650 mili giây và báo khi quá thời gian. Nếu mẫu thực tế gặp giới hạn, hãy thử lại bằng bộ máy regex và giới hạn đầu vào của môi trường sản xuất.
- Quantifier lồng nhauHình dạng kinh điển là nhóm có quantifier chứa token có quantifier — (a+)+, (\w+)* — trong đó nhiều cách chia cùng một chuỗi đều thỏa pattern bên trong.
- Phân nhánh mơ hồPhân nhánh mơ hồ cũng gây ra: (a|aa)+ cho engine hai cách khớp mỗi ký tự thêm, nhân đôi cây tìm kiếm theo từng ký tự.
- Sửa cấu trúcCách sửa mang tính cấu trúc: làm khớp bên trong rõ ràng, chặn nó bằng giới hạn độ dài tường minh, và luôn test dữ liệu suýt khớp chứ không chỉ dữ liệu hợp lệ.
Neo trước khi tin kết quả khớp
Pattern tìm thấy chuỗi con không phải pattern xác thực giá trị. /\d+/ khớp bên trong abc123xyz; /^\d+$/ chỉ chấp nhận chữ số. Hầu hết bug xác thực là thiếu neo, và hầu hết bug trích xuất là neo không nên có.
- Đầu và cuối^ và $ ghim khớp vào đầu và cuối chuỗi — hoặc của từng dòng khi bật flag multiline, thứ âm thầm thay đổi nghĩa của “toàn bộ dữ liệu nhập”.
- Ranh giới từRanh giới từ \b giữ pattern ngắn không khớp bên trong từ dài hơn: \bcat\b tìm con vật, không tìm cat trong concatenate.
- Search vs validateQuyết định search hay validate ngay từ đầu: pattern trích xuất thường không muốn neo, còn validator hầu như luôn muốn cả hai.
Test với dữ liệu mẫu thực tế
Pattern chứng minh trên ba ví dụ gọn gàng sẽ hỏng trong production ở ví dụ thật thứ tư. Xây bộ mẫu phản ánh phân phối dữ liệu nhập: giá trị hợp lệ dài nhất, chuỗi rỗng, biến thể khoảng trắng, tên Unicode, và cái suýt khớp mà không được khớp.
- Suýt khớpBao gồm cái suýt khớp: pattern email nên được test với a@b và a b@c.d, không chỉ với địa chỉ đúng chuẩn.
- UnicodeHãy thử tên có dấu và dữ liệu Unicode: với cờ u, dấu chấm xử lý theo điểm mã Unicode, nhưng \w không phải lớp chung cho mọi chữ Unicode. Dùng thuộc tính như \p{L} khi thích hợp.
- Chạy lại cả bộGiữ bộ mẫu cạnh pattern; khi pattern đổi, chạy lại cả bộ, không chỉ ca đã thúc đẩy thay đổi.
Flag đổi ngôn ngữ, không chỉ đổi tìm kiếm
Flag là một phần nghĩa của pattern. g quyết định bạn nhận khớp đầu tiên hay tất cả, i gộp hoa thường, m neo lại ^ và $ theo dòng, s cho dấu chấm vượt xuống dòng, và u chuyển engine sang chế độ hiểu Unicode với cú pháp nghiêm hơn.
Không gian làm việc đánh giá pattern với các flag bạn chọn và liệt kê mọi khớp kèm offset đầu và cuối, nhóm bắt đánh số và đặt tên với vị trí riêng, và bản xem trước thay thế trực tiếp — nên đổi flag hiện ra như khác biệt cụ thể trong kết quả, không phải lý thuyết.
- g và lastIndexKhông có g, test() và match() chỉ thấy khớp đầu tiên; có g, đối tượng regex mang trạng thái lastIndex khiến các lần gọi test() liên tiếp luân phiên kết quả — một bug production khét tiếng.
- s nới dấu chấms (dotAll) làm . khớp cả xuống dòng, có thể lặng lẽ nới khẩu vị của pattern cũ khi bật toàn cục.
- u và các bạnu cho phép cú pháp thoát nhận biết Unicode và quy tắc cú pháp chặt hơn; nó không biến \w hoặc \d thành lớp chung cho chữ hay chữ số Unicode. Công cụ còn hỗ trợ d, y và v.
Giữ pattern và mẫu cục bộ
Dữ liệu test thường là dữ liệu thật: email khách hàng, dòng log nội bộ, định danh từ báo cáo sự cố. Dán nó vào trình test online là gửi nó tới hạ tầng người khác. Trình test trong trình duyệt giữ phiên trong tab — pattern và văn bản mẫu được đánh giá bởi engine trên chính thiết bị của bạn và không bao giờ truyền đi.
Runtime cục bộ nói rõ trần của nó: pattern tối đa 4.096 ký tự, văn bản mẫu tối đa 100.000 ký tự, thay thế tối đa 20.000, và tối đa 1.000 khớp được báo mỗi lần chạy. Các giới hạn đó định cỡ cho phát triển và gỡ lỗi; phân tích log khối lượng lớn thuộc về script cục bộ, không phải tab trình duyệt.
Chỉ sao chép ra thứ bạn cần — pattern hoàn chỉnh và chuỗi thay thế — và để dữ liệu mẫu ở nơi nó bắt đầu: trên máy của bạn.
Test một pattern cục bộDữ liệu trích xuất thường đổ vào JSON.
Khi pattern rút giá trị ra khỏi văn bản thô, hãy kiểm tra và diff payload kết quả bằng quy trình cục bộ xác định.