Nếu là coder chắc hẵn đa số đều biết qua regex (viết tắt của Regular Expression, tên thuần Việt là biểu thức chính quy). Nó thường được sử dụng để validate chuỗi ký tự như email, ip address hay tìm kiếm/thay thế chuỗi... Regex khá hữu ích không chỉ trong code mà còn cách lĩnh vực khác. Trong bài viết này mình sẽ tổng hợp lại cách dùng cũng như những kinh nghiệm cá nhân trong khi sử dụng regex.

1. Giới thiệu

Trước khi đi vào chi tiết thì mình sẽ nhắc lại regex là gì?

Regular expression viết tắt là regex, regexp, regxp.
Tiếng việt gọi là biểu thức chính quy.

Regular expression là một chuỗi ký tự để định nghĩa một search pattern.

Bản chất thì search pattern là cách biểu diễn cho regular language (là một formal language). Có một cách biểu diễn cho regular language khác mà chắc là một số anh em đã học trong chương trình đại học đó là otomat hữu hạn (finite automaton) trong môn học Chương trình dịch. Có anh em nào còn nhớ cái này không?

Đồ thị biểu diễn số thực - otomat hữu hạn

Vì regex bản chất là tìm và thay thế chuỗi ký tự nên nó thường được tích hợp trong các ide hay các trình soạn thảo văn bản. Ngoài dân coder, dân văn phòng, viết sách, ... nếu biết cách sài regex cũng rất hữu ích cho công việc. Ví dụ như các xóa khoảng trắng thừa, thêm khoảng trắng vào sau các dấu câu, ...

Xóa space thừa trong M$ Word

2. Cú pháp

Hiện tại cách sử dụng regex ở shell linux, các ngôn ngữ lập trình hoặc các ứng dụng soạn thảo văn bản có cú pháp không hoàn toàn giống nhau. Nhưng bản chất đều dựa trên regular language.

Cú pháp ở trong shell linux ví như lệnh grep là theo chuẩn POSIX. Trong chuẩn POSIX thì nó bao gồm 3 kiểu cú pháp cho regex là: BRE (Basic Regular Expressions), ERE (Extended Regular Expressions), và SRE (Simple Regular Expressions). SRE đã bị deprecated và không còn được sử dụng.

Còn các ngôn ngữ lập trình như Java, Javascript, C#, ... sử dụng cú pháp regex tương tự như Perl/PCRE nên cú pháp regex giữa các ngôn ngữ lập trình gần như hoàn toàn giống nhau.

Mình sẽ không nói rõ sự khác nhau giữa cú pháp POSIX hay Perl. Trong bài viết này chỉ tập trung vào cú pháp được sử dụng cho Javascript. Những ngôn ngữ khác có thể khác một chút.

Character classes

Ký tự Mô tả Ví dụ
. Match với bất kỳ kí tự trừ ký tự xuống dòng.
Để match với tất cả dùng [\s\S]
[] Match với ký tự trong[]
Có thể dùng - để chỉ phạm vi ký tự
[a-zA-Z_] match với những ký tự a->z, A->Z_
[^] Match với ký tự chứa không chứa trong [^] [^a-zA-Z_] match với những ký tự không phải là a->z, A->Z_
\w Match với ký tự chữ, số và _
Tương đương với [A-Za-z0-9_]
\W Ngược lại với \w
\s Match với các loại ký tự khoảng trắng
Tương đương với [ \f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]
\S Ngược lại với \s
\d Match với số
Tương đương với [0-9]
\D Ngược lại với \d

Anchors

Ký tự Mô tả
^ Match với đầu chuỗi
$ Match với cuối chuỗi
\b Match với word boundary
\B Ngược lại với \b

Escaped characters

Ký tự Mô tả
\. Dùng để escape các ký tự đặc biệt +*?^$\.[]{}()|/.
Bên trong [] chỉ \-] cần escape
\000 Match ký tự theo mã octal
\xFF Match ký tự theo mã hexa
\uFFFF, \u{FFFF} Match ký tự theo mã hexa cho ký tự unicode
\t Match ký tự tab (code 9)
\n Match ký tự new line (code 10)
\v Match ký tự vertical tab (code 11)
\f Match ký tự form feed (code 12)
\r Match ký tự form feed (code 13)
\0 Match ký tự NULL (code 0)

Quantifiers and alternation

Ký tự Mô tả Ví dụ
+ Match với pattern phía trước một hoặc nhiều lần
? Match với pattern phía trước không hoặc một lần
Nếu trước ? là *, +, ?, {M,N} thì sẽ làm cho chúng match ít nhất có thể
1KmXjBeiKWVn5HXfMTXS0ak4vkHagdFyI
* Match với pattern phía trước không hoặc nhiều lần
{M} Match với pattern phía trước chính xác m lần
{M,} Match với pattern phía trước nhiều hơn hoặc bằng m lần
{M,N} Match với pattern phía từ m đến n lần
| Giống như toán tử or. Chú ý khi sử dụng cùng () thì nó sẽ là 1 nhóm https://regexr.com/5hf3f

Replace

Ký tự Mô tả
$& Toàn bộ string match
$1 string nhóm 1
$` string trước toàn bộ match
$' string sau toàn bộ match
$$ Escape $
\n, \t Ký tự đặc biệt

Ví dụ: https://regexr.com/5hepe
1wfnrGCOg0EuRfNr2gO_nAG5Mj8h3Tm-b

Group and references

Ký tự Mô tả Ví dụ
(ABC) Nhóm để dùng cho replace hoặc xử lý khác
\1 Match với nhóm trước đó https://regexr.com/5hemt
(?:ABC) Không nhóm https://regexr.com/5henl

Lookaround

Ký tự Mô tả Ví dụ
(?=ABC) Tiếng anh là Positive lookahead.
Match với ký tự phía sau main pattern nhưng không đưa vào kết quả
Chú ý là cái này ko phải nhóm
https://regexr.com/5henu
(?!ABC) Tiếng anh là Negative lookahead.
Không match với ký tự phía sau main pattern và không đưa vào kết quả
Chú ý là cái này ko phải nhóm
https://regexr.com/5heo1
(?<=ABC) Tiếng anh là Positive lookbehind.
Match với ký tự phía trước main pattern nhưng không đưa vào kết quả
Chú ý là cái này ko phải nhóm
https://regexr.com/5heod
(?<!ABC Tiếng anh là Negative lookahead.
Không match với ký tự trước main pattern và không đưa vào kết quả
Chú ý là cái này ko phải nhóm
https://regexr.com/5heog

3. Flag trong javascript

Ký tự Mô tả Ví dụ
i Không phân biệt hoa thường
g Tìm tất cả các match. Nếu ko có g flag thì nó sẽ chỉ trả về match đầu tiên 1UWq4qxUJV8T0cYoFlM5exkZ4uzxK6G2r
m Nếu flag này được bật thì ^,$ sẽ match với đầu dòng và cuối dòng. Nếu không thì match với đầu chuỗi và cuối chuỗi. Cái này chỉ khác biệt khi trong chuỗi có ký tự xuống dòng 1KSYU2mWFCjECLEnN5N0t6vtKDkbM6YQZ
s . match với tất cả ký tự kể cả newline

4. Replace trong vscode

Với anh em coder nếu có sài vscode thì có thể thử tính năng find/replace bằng regex với những modifiers sau cũng rất hữu ích.

Ký tự Mô tả
\L Viết thường toàn bộ
\l Viết thường chỉ ký tự đầu tiên
\U Viết hoa toàn bộ
\u Viết hoa chỉ ký tự đầu tiên
Ví dụ replace trong vscode

5. Kết bài

Trên đây mình đã giới thiệu về cách sử dụng của regex và một số kinh nghiệm của bản thân. Hy vọng nó giúp ích cho các anh em. Anh em nào biết rồi hoặc có gì hay thì góp ý, anh em nào còn mù mờ thì có thể xoá bớt sương mù. Thân chào anh em!!!