Dùng regex so sánh 2 chuỗi c năm 2024

Bạn đã từng bao giờ rơi vào trường hợp như mình chưa, cần kiểm tra định dạng một chuỗi có hợp lệ, hoặc tìm kiếm một chuỗi nằm trong một chuỗi dài khác. Đa số các bạn cần dùng đến việc validate [xác minh] tính hợp lệ của dữ liệu đều đã từ gặp phải câu hỏi đấy.

Nếu bạn gặp trường hợp lúc đấy giải pháp đầu tiên bạn nghĩ đến là gì nếu chưa biết gì về regex?

Có thể nó sẽ trở thành một bài toán khá hóc búa nếu bạn chỉ xử lý thuần tuý bằng cách duyệt chuỗi mà không có công cụ và thư viện xử lý.

Vậy regex là gì? Nó giải quyết bài toán không tưởng ở trên như thế nào? Nó cao siêuảo diệu ra sao?

Chúng ta hãy cùng đi tìm hiểu nào!

2. Giới thiệu

Theo anh wikipedia:

Biểu thức chính quy [regular expression, viết tắt là regexp, regex hay regxp] là một chuỗi miêu tả một bộ các chuỗi khác, theo những quy tắc cú pháp nhất định.

Cùng điểm một chút về lịch sử nhỉ.

Khái niệm regex được bắt đầu đưa ra từ những năm 1950 khi mà nhà toán học người Mỹ Stephen Cole Kleene chính thức mô tả một ngôn ngữ chính quy Khái niệm này được sử dụng phổ biến trong các tiện ích xử lý văn bản Unix. Sau đấy, từ những năm 1980, tồn tại các cú pháp khác nhau để tạo ra các biểu thức chính quy. Các chuẩn được đưa ra và sử dụng rộng rãi nhất là cú pháp Perl

Mỗi lần mình tìm hiểu xong một thời gian không dùng đến, lúc quay lại đọc đều có cảm giác như mới :].

3. Công dụng

Regex được sử dụng với rất nhiều mục đích khác nhau nhưng thường được dùng nhiều với mục đích đối sánh văn bản và kiểm tra cú pháp trong các trình biên tập văn bản và các tiện ích tìm kiếm và xử lý văn bản dựa trên các mẫu được quy định.

Ví dụ: Nếu bạn muốn tạo bộ lọc và muốn loại bỏ dữ liệu là những trang web mà người khác tạo ra, bạn có thể sử dụng biểu thức chính quy để loại trừ bất kỳ dữ liệu nào từ toàn bộ dải địa chỉ IP người khác sử dụng. Giả sử các địa chỉ IP đó có dải từ 198.51.100.1 - 198.51.100.25. Thay vì nhập 25 địa chỉ IP khác nhau, bạn có thể tạo biểu thức chính quy như 198\.51\.100\.\d* để đối sánh với toàn bộ dải địa chỉ.

4. Cách dùng

Các kí tự đặc biệt

Bảng 4.1 Các kí tự đặc biệt trong biểu thức chính quy. Kí tự [kí hiệu, cờ] Ý nghĩa

Tìm với luật dưới đây:

Một dấu gạch chéo ngược sẽ biến một kí tự thường liền kế phía sau thành một kí tự đặc biệt, tức là nó không được sử dụng để tìm kiếm thông thường nữa. Ví dụ, trường hợp kí tự '`mưa gió bão bùng`1' không có dấu gạch chéo ngược này sẽ được khớp với các kí tự 'b' in thường, nhưng khi nó có thêm dấu gạch chéo ngược, '`mưa gió bão bùng`2' thì nó sẽ không khớp với bất kì kí tự nào nữa, lúc này nó trở thành kí tự đặc biệt. Xem thêm phần để biết thêm chi tiết.

Tuy nhiên nếu đứng trước một kí tự đặc biệt thì nó sẽ biến kí tự này thành một kí tự thường, tức là bạn có thể tìm kiếm kí tự đặc biệt này trong xâu chuỗi của bạn như các kí tự thường khác. Ví dụ, mẫu `mưa gió bão bùng`3 có '*' là kí tự đặc biệt và mẫu này sẽ bị phụ thuộc vào kí tự này, nên được hiểu là sẽ tìm khớp với 0 hoặc nhiều kí tự a. Nhưng, với mẫu `mưa gió bão bùng`4 thì kí tự '`mưa gió bão bùng`5' lúc này được hiểu là kí tự thường nên mẫu này sẽ tìm kiếm xâu con là 'a*'.

Đừng quên \ cũng là một kí tự đặc biệt, khi cần so khớp chính nó ta cũng phải đánh dấu nó là kí tự đặc biệt bằng cách đặt \ ở trước [\\].

Khớp các kí tự đứng đầu một chuỗi. Nếu có nhiều cờ này thì nó còn khớp được cả các kí tự đứng đầu của mỗi dòng [sau kí tự xuống dòng].

Ví dụ, `mưa gió bão bùng`7 sẽ không khớp được với 'A' trong "an A" vì 'A' lúc này không đứng đầu chuỗi, nhưng nó sẽ khớp "An E" vì lúc này 'A' đã đứng đầu chuỗi.

Ý nghĩa của '^' sẽ thay đổi khi nó xuất hiện như một kí tự đầu tiên trong một lớp kí tự, xem phần để biết thêm chi tiết.

So khớp ở cuối chuỗi. Nếu gắn cờ multiline [đa dòng], nó sẽ khớp ngay trước kí tự xuống dòng.

Ví dụ, /t$/ không khớp với 't' trong chuỗi "eater" nhưng lại khớp trong chuỗi "eat".

Cho phép kí tự trước nó lặp lại 0 lần hoặc nhiều lần. Tương đương với cách viết {0,}.

Ví dụ, /bo*/ khớp với 'boooo' trong chuỗi "A ghost booooed" nhưng không khớp trong chuỗi "A birth warbled".

Cho phép kí tự trước nó lặp lại 1 lần hoặc nhiều lần. Tương đương với cách viết {1,}.

Ví dụ, /a+/ khớp với 'a' trong chuỗi "candy" và khớp với tất cả kí tự a liền nhau trong chuỗi "caaaaaaandy".

Cho phép kí tự trước nó lặp lại 0 lần hoặc 1 lần duy nhất. Tương đương với cách viết {0,1}.

Ví dụ, /e?le?/ khớp với 'el' trong chuỗi "angel" và 'le' trong chuỗi "angle" hay 'l' trong "oslo".

Nếu sử dụng kí tự này ngay sau bất kì kí tự định lượng nào trong số *,+,? hay {}, đều làm bộ định lượng "chán ăn" [dừng so khớp sau ngay khi tìm được kí tự phù hợp], trái ngược với đức tính "tham lam" vốn sẵn của chúng [khớp tất cả kí tự chúng tìm thấy]. Ví dụ, áp dụng biểu mẫu /\d+/ cho "123abc" ta được "123". Nhưng áp /\d+?/ cho chính chuỗi trên ta chỉ nhận được kết quả là "1".

Bạn có thể đọc thêm trong mục x[?=y] và x[?!y] của bảng này.

Dấu . khớp với bất kì kí tự đơn nào ngoại trừ kí tự xuống dòng.

Ví dụ, /.n/ khớp với 'an' và 'on' trong chuỗi "no, an apple is on the tree", nhưng không khớp với 'no'.

Khớp 'x' và nhớ kết quả so khớp này, như ví dụ ở dưới. Các dấu ngoặc tròn được gọi là các dấu ngoặc có nhớ.

Biểu mẫu `lụt không cần nước`4 trong chuỗi "foo bar foo bar". `lụt không cần nước`5 và `lụt không cần nước`6 trong mẫu khớp với 2 từ cuối.

Chú ý rằng `lụt không cần nước`5, `lụt không cần nước`6, `lụt không cần nước`9 được sử dụng để so khớp các phần trong regex, nó đại diện cho nhóm so khớp đằng trước. Ví dụ: `có thể chạy được`0

Cú pháp `có thể chạy được`1 được sử dụng trong việc thay thế các phần của một regex. Ví dụ: `có thể chạy được`2sẽ đảo vị trí 2 từ 'bar' và 'foo' cho nhau.

Khớp 'x' nhưng không nhớ kết quả so khớp. Những dấu ngoặc tròn được gọi là những dấu ngoặc không nhớ, nó cho phép bạn định nghĩa những biểu thức con cho những toán tử so khớp. Xem xét biểu thức đơn giản `có thể chạy được`4Nếu biểu thức này được viết là `có thể chạy được`5, `có thể chạy được`6 sẽ chỉ áp dụng cho kí tự 'o' ở cuối chuỗi 'foo'. Với những dấu ngoặc không nhớ, `có thể chạy được`7sẽ áp dụng cho cả cụm 'foo'.

Chỉ khớp 'x' nếu 'x' theo sau bởi 'y'.

Ví dụ, `có thể chạy được`9chỉ`tốc biến`0khớp với 'Jack' nếu đằng sau nó là 'Sprat'. `tốc biến`1chỉ khớp 'Jack' nếu theo sau nó là 'Sprat' hoặc 'Frost'. Tuy nhiên, cả 'Sprat' và 'Frost' đều không phải là một phần của kết quả so khớp trả về.

Chỉ khớp 'x' nếu 'x' không được theo sau bởi 'y'.

Ví dụ: `tốc biến`3 chỉ khớp với số không có dấu `lụt không cần nước`2 đằng sau. Biểu thức `tốc biến`5cho kết quả là '141' mà không phải '3.141'.

Khớp 'x' hoặc 'y'

Ví dụ, `tốc biến`7khớp với 'green' trong chuỗi "green apple" và 'red' trong chuỗi "red apple".

Kí tự đứng trước phải xuất hiện n lần. n phải là một số nguyên dương.

Ví dụ, `tốc biến`9không khớp với 'a' trong "candy", nhưng nó khớp với tất cả kí tự 'a' trong "caandy", và khớp với 2 kí tự 'a' đầu tiên trong "caaandy".

Kí tự đứng trước phải xuất hiện từ n đến m lần. n và m là số nguyên dương và n

Chủ Đề