Regular Expression trong PHP

(Ngày: 17/10/2019)
Regular Expression thường được dùng để xử lý chuỗi thông qua biểu thức riêng của nó. Để các biểu thức này có thể hoạt động được bạn cần tuân thủ nhiêm ngặt theo các quy tắc viêt biểu thức của Regular.

Khai báo chuỗi

Một chuỗi Regex được bắt đầu bằng ký tự "/" và kết thúc cũng bới ký tự "/". Ta có thể xét một ví dụ đơn giản như sau:

$pattern = '/abc/';
$subject = 'abc';
if (preg_match($pattern, $subject)){
    echo 'Chuỗi $subject có chứa chuỗi $pattern';
}

Trong ví dụ trên, $pattern = '/abc/' có ý nghĩa là tìm trong chuỗi $subject có chứa chuỗi 'abc' hay không. Vì chúng ta truyền vào $subject là 'abc' cho nên kết quả thu được sẽ là thông báo có chứa chuỗi.

So sánh tuyệt đối

Cũng xét ví dụ ở trên, nếu chúng ta truyền vào với giá trị như sau thì điều gì sẽ xảy ra:

$pattern = '/abc/';
$subject = 'mabcdef';
if (preg_match($pattern, $subject)){
    echo 'Chuỗi $subject có chứa chuỗi $pattern';
}

Kết quả trả về vẫn là đúng bởi vì tách nhỏ chuỗi $subject ra thì bên trong nó vẫn chứa chuỗi 'abc'.

Vấn đề đặt ra ở đây là bạn muốn kiểm tra trong $subject trùng khớp với $pattern hay không thì phải làm thế nào?

Trong lập trình, để kiểm tra hai biến có bằng nhau hay không đơn giản chúng ta chỉ cần sử dụng toán tử so sánh '=='. Nhưng trong Regex chúng ta phải làm thế nào? Câu trả lời là bạn chỉ cần thêm ký tự '^' và '$' vào đầu và cuối của chuỗi $pattern. Khí đó, khi so sánh sẽ tiến hành so sánh từ đầu tới cuối của chuỗi được truyền vào.

$pattern = '/^framgia$/';
$subject = 'framgia';
if (preg_match($pattern, $subject)){
    echo 'So sánh trùng khớp hoàn toàn';
}

Bây giờ nếu chúng ta thay đổi chuỗi $subject thành 'sframgia01' thì kết quả thu được sẽ là sai.

Phạm vi của chuỗi

Trong một số trường hợp, bạn cũng cần so sánh một chuỗi ký tự có thuộc một khoảng giá trị bất kỳ nào không. Chẳng hạn chuỗi có phải ký tự in thường, ký tự in hoa, có phải là số,... Và để làm được điều này chúng ta sử dụng 1 trong 2 phương thức sau:

  • [min-max]: min là ký tự bắt đầu. max là ký tự kết thúc
  • [list-char]: với list-char là danh sách các ký tự cho phép.

Xét ví dụ sau:

//Kiểm tra chuỗi chỉ là ký tự in thường
$pattern = '/[a-z]/';
$subject = 'abcd';
if (preg_match($pattern, $subject)){
    echo 'true';
}
//Kiểm tra chuỗi chỉ là ký tự in HOA
$pattern = '/[A-Z]/';
$subject = 'ABCDGH';
if (preg_match($pattern, $subject)){
    echo 'true';
}
//Kiểm tra chuỗi chỉ chứa số
$pattern = '/[0-9]/';
$subject = '123678';
if (preg_match($pattern, $subject)){
    echo 'true';
}
//Kiểm tra chuỗi chỉ là ký tự in HOA hoặc in thường
$pattern = '/[A-Za-z]/';
$subject = 'ABCbvnDGH';
if (preg_match($pattern, $subject)){
    echo 'true';
}

 

Quy định chiều dài cho chuỗi

Để quy định độ dài cho chuỗi ta dùng {min,max}. Trong đó, min là chiều dài tối thiểu, max là chiều dài tối đa.

$pattern = '/^[a-z]{5,10}$/';
$subject = 'fdsfdsa';
if (preg_match($pattern, $subject)){
    echo 'True';
}

Với $pattern như ví dụ trên. Kết quả trả về là true chỉ khi nào $subject chỉ chứa các ký tự in thường và có chiều dài từ 5 đến 10 ký tự.

Regex đại diện cho 1 ký tự

Nếu chỉ muốn kiểm tra ký tự cuối cùng xuất hiện trong chuỗi còn những ký tự trước nó không giới hạn phạm vi thì phải viết Regex như thế nào? Regex cung cấp cho chúng ta ký tự '.'. Với ký tự này được khai báo, Regex sẽ chấp nhận bất cứ ký tự nào đc khai báo.

// Pattern là ký tự bất kỳ dài từ 3 đến 10 ký tự
$pattern = '/^.{3,10}$/';
$subject = '3232';
if (preg_match($pattern, $subject)){
    echo 'True';
}

Regex với ký hiệu đặc biệt

Giả sử bạn muốn kiểm tra chuỗi có chứa dấu . hay không. Nếu cứ làm như trước đây thì chúng ta có:

$pattern = '/./';
$subject = 'demo';
if (preg_match($pattern, $subject)){
    echo 'True';
}

Kết quả của chương trình này sẽ là True. Bởi vì Regex hiểu dấu . là chấp nhận bất kỳ giá trị nào chứ không phải là yêu cầu kiểm tra trong chuỗi có dấu . hay không. Khi gặp những tình huống tương tự như trên, bạn hãy làm như sau:

$partern = '/\./';
$subject = 'demo';
if (preg_match($partern, $subject)){
    echo 'Chuỗi regex so khớp';
}

Kết quả của chương trình này là false. Vì trong chuỗi $subject không có chứa ký tự '.'.

Regex với Or

Muốn kiểm tra chuỗi có ký tự A hoặc ký tự B hay không thì thực hiện theo sau:

$pattern = '/^A|B$/';
$subject = 'A';
if (preg_match($pattern, $subject)){
    echo 'Chuỗi regex so khớp';
}

 

Regex với chiều dài không giới hạn

Ta đã biết được muốn xác định chiều dài cho chuỗi thì dùng {min, max}. Tuy nhiên vẫn còn một số cách ngắn gọn hơn nhiều.

  • Ký tự *: Đại diện cho ký tự null và nhiều ký tự.
$pattern = '/[a-z]*/';
$subject = 'dsada';
if (preg_match($pattern, $subject)){
    echo 'True';
}
  • Ký tự +: Đại diện cho một hoặc nhiều ký tự.
// chuỗi ít nhất có 1 ký tự chữ thường
$pattern = '/[a-z]+/';
$subject = 's';
if (preg_match($pattern, $subject)){
    echo 'True';
}
  • Ký tự ?: Đại diện cho một hoặc không có ký tự nào.
// chuỗi có 1 hoặc không có ký tự thường nào
$pattern = '/[a-z]?/';
$subject = 's';
if (preg_match($pattern, $subject)){
    echo 'True';
}

 

Các ký tự Regex đặc biệt

Danh sách các ký tự Regex đặc biệt như sau:

  • \d : Chữ số bất kỳ ~ [0-9].
  • \D : Ký tự bất kỳ không phải là chữ số (ngược với \d) ~ [^0-9].
  • \w : Ký tự từ a-z, A-Z, hoặc 0-9 ~ [a-zA-Z0-9].
  • \W : Ngược lại với \w (nghĩa là các ký tự không thuộc các khoảng: a-z, A-Z, hoặc 0-9) ~[^a-zA-Z0-9].
  • \s : Khoảng trắng (space).
  • \S : Ký tự bất kỳ không phải là khoảng trắng.

Website kiểm tra Regex online

Không phải lúc nào chúng ta cần kiểm tra một Regex cũng lại mở code ra gõ lệnh rồi chạy chương trình chờ kết quả trả về. Việc này rất mất thời gian mà lại không cần thiết. Các bạn có thể tìm kiếm một trang kiểm tra regex bất kỳ nào trên google. Có rất nhiều để các bạn lựa chọn.

Bạn có thể sử dụng Regex online. Hãy nhập regex vào ô Regular Expression. Sau khi hoàn thành regex thì hãy nhập chuỗi cần kiểm tra vào ô Test String.

Giao diện chính của trang này:

Chúc mọi người thành công khi làm việc với Regex.

>> Có thể bạn quan tâm: Hướng dẫn cài đặt và tổng quan về PHP

viblo.asia