Lập trình 22/09/2026 5 phút

ReDoS: vì sao một regex 6 ký tự có thể treo cả server của bạn

Mẫu (a+)+$ trông vô hại, nhưng gặp đúng input độc nó chạy chậm theo cấp số nhân. Bài này đo thật: với chuỗi 'aaaa...!', python re mất 9 giây chỉ với 28 ký tự, và thời gian gấp đôi mỗi khi thêm một 'a' — n=40 sẽ mất hàng ngàn năm. Cùng mẫu đó trên Go RE2 chỉ mất 3 micro-giây, kể cả với 100.000 ký tự. Đây là ReDoS, và cách phòng nó.

Lập trình 22/09/2026 6 phút

RE2 và Go regexp: cỗ máy đánh đổi tính năng để không bao giờ nổ

RE2 (Go, Rust, Google) chạy tuyến tính bằng cách mô phỏng mọi trạng thái cùng lúc thay vì thử-và-quay-lui. Bài này đo thật: cùng mẫu độc (a+)+b, RE2 xử lý 20 triệu ký tự trong 443ms với ns/ký tự hằng số ~22 — trong khi python treo ở 28 ký tự. Cái giá: RE2 từ chối lookahead, lookbehind và backreference, mỗi cái báo một lỗi khác nhau. Khi nào nên chọn nó.

Lập trình 22/09/2026 6 phút

Lookahead và lookbehind: nhìn quanh mà không nuốt, và cái giá của nó

Lookaround cho regex khả năng khẳng định điều kiện về ngữ cảnh mà không tiêu thụ ký tự. Bài này đo thật bằng python: chèn dấu phẩy nghìn '1234567' thành '1,234,567' bằng (?<=\d)(?=(\d{3})+$), kiểm mật khẩu mạnh bằng ba lookahead cùng vị trí, lấy số sau $ bằng (?<=\$)\d+, và bỏ 'cats' bằng cat(?!s). Vì sao những phép này mạnh — và vì sao RE2 từ chối chúng.

Lập trình 22/09/2026 6 phút

Unicode trong regex: vì sao \w cắt cụt chữ tiếng Việt và 'à' đôi khi không khớp

Regex và tiếng Việt là mỏ bug ít người lường trước. Bài này đo thật: python \w bắt 'chào' nguyên vẹn nhưng [a-zA-Z] cắt thành 'ch','o'; Go \w lại chỉ ASCII nên phải dùng \p{L}. Chữ 'à' có hai cách mã hóa (NFC 1 codepoint, NFD 2 codepoint) trông giống hệt mà regex khớp khác nhau. Và . khớp 1 rune chứ không phải 1 byte. Cách xử lý cho đúng.

Lập trình 22/09/2026 6 phút

Nhóm bắt và thay thế: dùng regex để biến đổi chuỗi, không chỉ để tìm

Regex không chỉ tìm — nó trích và dựng lại. Bài này đo thật: nhóm (...) cắt '2026-09-22' thành ba phần, nhóm đặt tên (?P<nam>) đọc bằng tên, re.sub đổi 'yyyy-mm-dd' thành 'dd/mm/yyyy' bằng \3/\2/\1, sed đổi 'Nguyen Van A' thành 'Van A, Nguyen'. Và vì sao (?:...) không được đếm lại quan trọng: thêm một cặp () thừa làm \1 trong thay thế trỏ sai.

Lập trình 22/09/2026 6 phút

Tối ưu regex: bốn mẹo đo được, và một mẹo biến 2 giây thành 0.33 micro-giây

Regex chậm hiếm khi vì máy yếu — thường vì mẫu viết chưa khéo. Bài này đo thật bốn kỹ thuật: biên dịch một lần (nhanh 1.84x), lớp phủ định thay lazy (chênh nhỏ nhưng an toàn hơn), atomic/possessive chặn backtracking (2222ms xuống 0.33µs), và neo để loại sớm (68ms xuống 0.21µs, nhanh hơn 329 nghìn lần). Kèm nguyên tắc quan trọng nhất: đo trước khi tối ưu.