- Biểu thức chính quy
- Biểu thức cơ bản
- Các ký tự mô tả
- - Dấu chấm .
- - Tập ký tự []
- - Tập ký tự loại trừ [^]
- - Lặp lại *
- - Lặp lại +
- - Mẫu phía trước có hoặc không : ?
- - Số lượng {}
- - Nhóm ( ... )
- - Thay thế |
- - Ký tự đặc biệt \
- - Bắt đầu ^
- - Kết thúc $
- - Ký hiệu viết tắt cho tập hợp
- Lookahead ?=
- Not lookahead ?!
- Lookbehind ?<=
- Lookbehind ?<!
- Cờ thiết lập
- Tóm tắt về RegEx
Biểu thức chính quy - Regular expression
Biểu thức chính quy là gì?
Biểu thức chính quy là một nhóm các ký tự, ký hiệu viết ra theo quy luật tạo thành mẫu (pattern), nó được sử dụng để tìm kiếm văn bản (text).
Một biểu thức chính quy là một mẫu (pattern) nó tương đồng quy luật với một chuỗi từ trái qua phải. Biểu thức chính quy tên tiếng anh là Regular Expression gọi tắt là regex hoặc regexp
Trong lập trình nó được dùng với các hàm xử lý chuỗi, xử lý văn bản với các tác vụ cụ thể như: tìm và thay thế chuỗi, kiểm tra tính hợp lệ của dữ liệu, trích xuất chuỗi con từ một chuỗi ... Hầu hết các ngôn ngữ lập trình đều hỗ trợ (Biểu thức chính quy trong PHP, trong Java, trong C# ...) PHP, C#, JAVA ... Thậm chí RegExp còn rất phổ biến trong các ứng dụng, công cụ khác nhau như rewrite URL mod_rewrite, tìm kiếm và thay thế trong các IDE, truy vấn lọc dữ liệu trong một số dịch vụ của Google ...
Thử xem xét một ví dụ về Regex:
Giả sử ứng dụng của bạn yêu cầu tên người dùng phải tuân thủ quy tắc:
- (1) Tên được phép chứa các ký tự, các số, gạch dưới, gạch nối.
- (2) Tên phải có độ dài trong khoảng cho phép từ 3 đến 15 ký tự.
Thì biểu thức chính quy biểu diễn quy tắc đó sẽ như sau:
^[a-z0-9_-]{3,15}$
^
: Ký hiệu cho biết bắt đầu một dòng[a-z0-9_-]
: Cho biết là tập tự: a-z, số từ 0 - 9, ký tự -, ký tự _{3,15}
: Chuỗi dài 3 đến 15 ký tự$
: Điểm kết thúc dòngVới mẫu như trên, chuỗi phù hợp đọc từ trái qua phải thì: bắt đầu một dòng - đến tập ký tự chỉ chứa (a-z, 0-9, -, _), chuỗi này dài 3 - 15, cuỗi cùng là kết thúc dòng.
Với biểu thức chính quy trên thì các tên như xuanthu
, xuan-xhu
, xuanxhu_123
... được chấp nhận phù hợp với mẫu. Còn mẫu không phù hợp như ab
(nhỏ hơn 3 ký tự), abc@dx
(chứa
ký tự không cho phép) ...
Biểu thức RegExp cơ bản
Xét trường hợp đơn giản nhất, một biểu thức Regex chỉ là một mẫu là chuỗi các ký tự dùng để tìm kiếm trong văn bản.
(chuỗi, text, string). Ví thụ một biểu thức RegEx ước
,
thì phù hợp với nó là bắt đầu bằng ư
theo sau là ớ
và tiếp theo là c
,
mang biểu thức đó so khớp với đoạn text (văn bản) thì thấy hợp mẫu như sau:
ước => Ước một điều ... mộng ước rất đơn sơ. Nụ hôn trao hạnh phút đến bất ngờ (Chạy thử vidu01)
Biểu thức chính quy Regex là phân biệt chữ hoa chữ thường. Có cơ chế bật cờ thiết lập không phân biệt chữ hoa, chữ thường ở phần dưới
Các ký tự biểu diễn thông tin siêu dữ liệu - Meta
Các ký hiệu biểu diễn thông tin (meta character), được dùng để viết biểu thức chính quy RegEx, tóm tắt lại và giải thích chi tiết từng mục ở phần sau:
Nếu có thể, sau khi đọc và hiểu các giải thích ở phần sau, hãy cố gắng nhớ bảng này, nó sẽ giúp bạn đọc hiểu và viết biểu thức chính quy được dễ dàng.
Ký tự Meta | Mô tả |
---|---|
. | Ký hiệu chấm. Biểu diễn bất kỳ ký tự nào ngoài trừ ký tự xuống dòng |
[ ] | Mô tả một tập hợp các ký tự, các mẫu. |
[^ ] | Tập hợp ký tự phủ định. Phù hợp nếu không có ký tự nào trong [^ ] |
* | Lặp lại 0 đến nhiều lần. |
+ | Lặp lại 1 hoặc nhiều lần |
? | Tùy chọn có hay không cho mẫu phía trước |
{n,m} | Độ dài tối thiểu là n tối đa là m |
(xyz) | Biểu diễn một nhóm ký tự (có xét đến thứ tự của các ký tự). |
| | Biểu diễn thay thế, (phép toán or , hoặc) |
\ | Dùng để biểu diễn ký tự đặc biệt [ ] ( ) { } . * + ? ^ $ \ | |
^ | Điểm bắt đầu của dòng. |
$ | Điểm kết thúc của dòng |
Ký hiệu chấm .
Ký hiệu dấu chấm .
là một meta đơn giản, nó biểu diễn bất kỳ ký tự nào ngoài trừ ký tự return \r
hoặc newline \n
.
Ví dụ biểu thức RegEx .oàn
thì có nghĩa là: một ký tự nào đó, tiếp theo đến ký tự o
, tiếp theo đến
à
cuối cùng là n
.
Ví dụ dùng mẫu đó tìm trong chuỗi.
.oàn =>Sự hoàn hảo dường như không thể đạt được, nhưng nếu chúng ta theo đuổi sự hoàn hảo thì chúng ta sẽ chạm đến sự xuất sắc. (Chạy thử vidu02)
Cứ có 4 ký tự liên tiếp, bắt đầu bằng ký tự nào đó, sau đó là oàn thì phù hợp với mẫu.
Tập hợp ký tự []
Dùng []
để chứa tập hợp các ký tự viết ở bên trong nó, như tập [abc]
,
phù hợp với nó là bất kỳ ký tự nào có trong tập đó.
Có thể dùng dấu -
để biểu diễn một dải các ký tự theo
vị trí trong bảng chữ cái như a-z
(ký tự thường từ a đến z), 0-9
(số từ 0 đến 9),
A-Z
(chữ in từ A đến Z) ...,
biểu thức so sánh sẽ hợp mẫu nếu chứa bất kỳ ký tự nào trong đó (không cần quan tâm thứ tự)
Ví dụ biểu thức [ưƯ]ớc
có nghĩa là: Có một chữ ư
hoặc Ư
, theo sau bởi ớ
,
tiếp theo là c
[ưƯ]ớc => Ước một điều ... mộng ước rất đơn sơ. Nụ hôn trao hạnh phút đến bất ngờ (Chạy thử vidu03)
Lưu ý: Viết [.]
thì nó biểu diễn ký tự chấm .
chứ không con ý nghĩa đại diện bất kỳ ký tự nào như trường hợp trên.
nh[.] => Thời gian cứ thế xoay vòng thật nhanh. Bao mùa chiếc áo phông phanh! Chạy thử vidu04
Mẫu phù hợp là 3 ký tự liên tiếp: nh.
Tập hợp ngoại trừ [^]
Thông thường thì ^
biểu diễn điểm bắt đầu của chuỗi, tuy nhiên nếu nó nằm ở vị trí sau dấu [
của cặp []
thì nó lại mang ý nghĩa tạo ra tập hợp ký tự loại trừ (phụ định).
Ví dụ biểu thức [^n]hanh
có nghĩa là bất kỳ ký tự nào ngoại trừ ký tự n
, theo sau bởi h
,
tiếp theo bởi a
, n
và h
[^n]hanh => Thời gian cứ thế xoay vòng thật nhanh. Bao mùa chiếc áo phông phanh! Chạy thử vidu05
Lặp lại với ký hiệu *
Ký hiệu *
cho biết có sự lặp lại 0 hoặc nhiều lần mẫu phù hợp đứng phía trước nó
(như ký tự phía trước, tập [] phía trước, nhóm () phía trước ...).
Ví dụ mẫu xuanthula*b
thì sau ký tự l
có 0 hoặc nhiều ký tự a
liên tiếp
rồi đến ký tự *
nó đi sau tập hợp thì lặp tập hợp đó lặp lại 0 hoặc nhiều lần.
Ví dụ [a-z]*
là dòng có 0 hoặc n ký tự viết thường.
*
có thế sử dụng với dấu chấm .*
để biểu diễn bất kỳ chuỗi nào, hay dùng mẫu (.*)
*
có thể sử dụng với ký tự trắng (trong RegEx khoảng trắng viết là \s
)
để biểu diễn bất kỳ khoảng trắng nào.
Ví dụ \s*mình\s*
có nghĩa bắt đầu bởi không hoặc nhiều khoảng trắng, tiếp theo là ký tự
m
, ì
, n
, h
tiếp theo là không hoặc nhiều khoảng trắng.
"\s*mình\s*" => Đừng so sánh mình với bất cứ ai trong thế giới này. Nếu bạn làm như vậy có nghĩa bạn đang sỉ nhục chính bản thân mình. Bill Gates Chạy thử vidu06
Lặp lại với ký hiệu +
Ký hiệu +
tương tự như *
nhưng lặp lại 1 hoặc nhiều (ít nhất một lần). Ví dụ
có.+!
có nghĩa ký tự bắt đầu bằng có
theo sau ít nhất một ký tự nào đó (một hoặc nhiều ký tự),
cuối cùng là ký tự !
.
có.+! => Đàn ông cần tiền chủ yếu chỉ để cho hai việc: có được nàng và thoát được nàng!. Chạy thử vidu07
Mẫu phía trước có hay không đều được với ?
Trong biểu thức Regex thông thường ?
là một tùy chọn cho biết mẫu phía trước nó có thể có hoặc không. Ví dụ
[h]?ôn
nghĩa là tùy chọn có h
hoặc không,
theo sau là ô
, tiếp theo là n
[h]?ôn => Đàn bà khôn ngoan hơn đàn ông vì họ biết ít hơn, nhưng hiểu nhiều hơn. Chạy thử vidu08
Biểu diễn độ dài {}
{}
là biểu diễn số lượng, nó chỉ ra số lần mà một ký tự hoặc một nhóm các ký tự lặp lại.
Viết {min, max}
có nghĩa số lượng tối thiểu min và tối đa max.
Ví dụ [0-9]{2,3}
có nghĩa là có tối thiểu 2 tới 3 ký tự số.
Nếu bạn viết {min,}
có nghĩa tối thiểu có min lần lặp lại (số lượng min). Ví dụ [0-9]{2,}
có nghĩa là chuỗi có 2 hoặc nhiều ký tự số.
Nếu viết {number}
thì biểu diễn chính xác số lần lặp lại. Ví dụ [0-9]{3}
có nghĩa là chuỗi chính xác có 3 ký tự số.
Nhóm mẫu (...)
Nhóm là một mẫu (pattern) viết trong ()
ví dụ (ab)
. Thường dùng nhóm như là một mẫu con trong
một mẫu lớn. Ví dụ (ab)*
: thì (ab) là mẫu con, trong mẫu lớn thì nó lặp lại 0 hoặc nhiều lần => lặp lại ab
0 hoặc nhiều lần.
Chúng ta cũng dùng ký hiệu |
bên trong nhóm như là phép toán or
(hoặc) để xác định nhóm.
Ví dụ n(g|h)
có nghĩa bắt đầu bằng n
theo sau là một mẫu con,
mẫu đó hoặc là chữ g
hoặc là chữ h
. Thế thì các chuỗi nhỏ như nh
, ng
thì phù hợp.
n(g|h) =>Nếu có một ai đó làm chậm bước chân của bạn, hãy nhẹ nhàng rẽ sang hướng khác. Chạy thử vidu09
Viết mẫu như trên còn gọi là capture group vì các ngôn ngữ lập trình triển khai RegEx sẽ nhớ thông tin mẫu con này trong thông tin kết quả trả về.
Nếu chỉ cần lấy kết quả mẫu chính (không quan tâm mẫu con trả về, mặc dù phải phù hợp với mẫu con thì mẫu chính mới phù hợp)
thì cho thêm ký hiệu ?:
sau ký hiệu (
. Ví dụ: n(?:g|h)
Phân biệt capture group và non capture group thực ra cần xét trong một ngôn ngữ lập trình cụ thể, lấy ví dụ Javascript (bạn có thể chạy ngay trong trình duyệt để kiểm tra).
<script> // CAPTURE // Tạo biểu thức chính quy với mẫu là: n(g|h) // Sau đó so mẫu với chuỗi: 'hướng khác' const regex = new RegExp('n(g|h)'); const kq = regex.exec('hướng khác'); console.log(kq); // mảng kq: /* ['ng', 'g', index: 3, input: 'hướng khác', groups: undefined] */ </script>
Trong mảng kết quả trả về, có chuỗi phù hợp với mẫu lớn tìm được là ng
, nó cũng cho
biết luôn tương là mẫu con g
.
<script> // NON CAPTURE // Tạo biểu thức chính quy với mẫu là: n(?:g|h) // Sau đó so mẫu với chuỗi: 'hướng khác' const regex = new RegExp('n(?:g|h)'); const kq = regex.exec('hướng khác'); console.log(kq); // mảng kq: /* ['ng', index: 3, input: 'hướng khác', groups: undefined] */ </script>
Kết quả trả về tìm được ng
phù hợp với mẫu lớn, nhưng không chứa thông tin mẫu con (không nhớ).
Biểu diễn thay thế |
Ký tự |
chính là phép toán hoặc (or) kết hợp giữa các mẫu con, như (a|b|c)
, abc|xyz
,
(pattern1)|(pattern2)
... Xem các ví dụ phía trên, đã sử dụng |
Biểu diễn ký tự đặc biệt với \
Do một số ký hiệu đã được dùng đã biểu diễn Regex như : { } [ ] / \ + * . $ ^ | ?
nên để biểu diễn các ký tự đó dùng ký hiệu \
trước ký tự.
"(f|c|m)at\.?"
=> The fat cat sat on the mat.
Bắt đầu của dòng ^
Sử dụng ^
để kiểm tra các ký tự đàu tiên của dòng phù hợp với mẫu viết sau ^
.
Ví dụ ^a
thì chuỗi phù hợp khi bắt đầu là chữ a
có dạng như abcxyz
,
nếu vẫn chuỗi đó nó lại không phù hợp với ^b
.
^(T|t)he
có nghĩa là T
hoặc t
bắt đầu của chuỗi, theo sau là he
.
^(Trần|Lê).*
lấy là các dòng bắt đầu bằng Trần
hoặc Lê
Điểm kết thúc của chuỗi $
Cho biết kết thúc dòng phải thỏa mãn mẫu phía trước
Ngược lại với ^
ví dụ (at\.)$
nghĩa là cuối chuỗi có at.
thì là phù hợp.
"(at\.)$"
=> The fat cat. sat. on the mat.
Ký hiệu tắt cho tập hợp
Viết tắt | Diễn tả |
---|---|
. | Bất kỳ ký tự nào ngoại trừ xuống dòng |
\w | Chữ,sô, và _, tương đương với: [a-zA-Z0-9_] |
\W | Ngoài bảng chữ cái, tương đương với: [^\w] |
\d | Các số: [0-9] |
\D | Không phải số: [^\d] |
\s | Là ký tự trắng, tương đương với: [\t\n\f\r\p{Z}] |
\S | Không phải ký tự trắng: [^\s] |
Biểu thức ?=
lookahead (?=...)
Một biểu thức con viết bắt đầu bằng ?=
gọi là lookahead
(là một loại non-capture,
chỉ để khớp mẫu, không nhớ kết quả).
Biểu thức lookahead cho vào để lọc kết quả phía trước nó,
kết quả trả về (biểu thức phía trước) là phần đầu của mẫu khớp - phần sau không trả về
phải thỏa mãn lookahead
.
Ví dụ (T|t)he(?=\sfat)
thì lookahead
là (?=\sfat)
-
nghĩa là kết quả trả về khi ở trong chuỗi gốc nó được theo sau bởi fat
Ví dụ, lấy ra từ The
hoặc the
(T|t)he => The fat cat sat on the mat. Chạy thử vidu10
Lấy ra từ The
hoặc the
, nhưng từ đó phải đứng trước từ fat
(T|t)he(?=\sfat) => The fat cat sat on the mat. Chạy thử vidu11
Biểu thức ?!
phủ định lookahead (?!...)
Biểu thức (?! ...)
là lấy ra kết quả, mà kết quả này ở trong chuỗi gốc phía sau nó không được
thỏa mãn biểu thức viết trong (?! ...)
Ví dụ lấy ra từ The
hoặc the
, nhưng từ đó trong chuỗi gốc đằng sau không có fat
(T|t)he(?!\sfat) => The fat cat sat on the mat. Chạy thử vidu12
Biểu thức (?<=...)
Lookbehind
Cũng là loại non-capture, sử dụng đề lọc kết quả phía sau nó.
Kết quả trả về trong chuỗi gốc, phía trước nó phải thỏa mãn lookbehind.
(?<=(T|t)he\s)(fat|mat)
có nghĩa lấy tất cả các từ fat
hoặc mat
sau các từ The
hoặc the
Lấy ra các từ mat
hoặc cat
, nhưng trong chuỗi gốc - phía trước nó phải có
The
hoặc the
(?<=(T|t)he\s)(fat|mat) => The fat cat sat on the mat. Chạy thử vidu13
Biểu thức (?<!...)
phủ định Lookbehind
Sử dụng để lấy các phù hợp mà đi trước không có một mẫu lookbehind chỉ ra.
(?<!(T|t)he\s)(cat) => The cat sat on cat. Chạy thử vidu14
Các cờ
Cờ | Diễn tả |
---|---|
i | Thiết lập không phân biệt chữ hoa chữ thường |
g | Tìm toàn bộ kết quả (không dừng lại khi thấy kết quả đầu tiên). |
m | Xử lý nhiều dòng (khi chuỗi input nhiều dòng, mỗi dòng được mang ra khớp mẫu). |
Các cờ này được đưa vào mẫu theo dạng /RegExp/flags
"/The/gi"
=> The fat cat sat on the mat.
"/.(at)/"
=> The fat cat sat on the mat.
"/.(at)/g"
=> The fat cat sat on the mat.
"/.at(.)?$/gm"
=> The fat
cat sat
on the mat.
Trong PHP các hàm sử dụng RegExp thường các biểu thức này nằm trong cặp /../
Tóm tắt
Ký hiệu | Mô tả |
---|---|
. | Ký tự bất kỳ. |
[ ] | [..] Mô tả một tập hợp các ký tự, các mẫu. Còn [^...]
là phủ định của [], phù hợp nếu không có ký tự nào trong [^ ].Đặc biệt:
|
[^ ] | |
* | Lặp lại 0 đến nhiều lần. |
+ | Lặp lại 1 hoặc nhiều lần |
? | Tùy chọn có hay không cho mẫu phía trước đều được. |
?!... | Lookahead. (non-capture) Kết quả trả về khi ở trong chuỗi gốc, nó đứng trước chuỗi thỏa mãn lookahead. |
{min,max} | Độ dài. {min, } độ dài tối thiểu, {number} độ dài chính xác. |
(xyz) | Capture group. Biểu diễn nhóm mẫu và nhớ kết quả trả về. |
| | Thay thế (phép toán or , hoặc) |
\ | Dùng để biểu diễn ký tự đặc biệt [ ] ( ) { } . * + ? ^ $ \ | |
^ | Điểm bắt đầu của dòng. |
\A | Điểm bắt đầu của chuỗi input. |
$ | Điểm kết thúc của dòng |
\z | Điểm kết thúc chuỗi input |
Luyện tập phân tích với một số biểu thức chính quy thông dụng
Một số mẫu để kiểm tra dữ liệu, tìm kiếm, trích xuất ...
Địa chỉ email
^([a-zA-Z0-9._%-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})*/$
[a-zA-Z0-9._%-]+
: phần đầu - phải có một chuỗi hình thành từ các ký trong mẫu@
: tiếp theo đến ký tự @[a-zA-Z0-9.-]+
: tiếp theo phải có một chuỗi hình thành bởi các ký tự trong mẫu\.
: tiếp theo phải có ký tự .[a-zA-Z]{2,4}
: phần cuối có chuỗi dài 2 - 4 hình thành bởi các ký tự chữ cái.
Đia chỉ IP4
^((?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))*$
Tác giả: https://twitter.com/ziishaned