Hàm preg_split trong PHP

Hàm preg_split dùng để cắt chuỗi dựa trên mẫu phân cách mà bạn muốn. Ví dụ sẽ làm bạn sẽ hiểu hơn nhiều.

Ví dụ 1, phân tách từ dựa trên khoảng trắng giữa chúng (mẫu phân cách):

$str = "nguyễn đức anh";
$pt = '/\s+/';
$rs = preg_split($pt, $str);
print_r($rs);

Kết quả:

Array ( [0] => nguyễn [1] => đức [2] => anh )

Một mảng gồm 3 phần tử, chứa các từ không tên.

Ví dụ 2, tôi tham khảo luôn từ W3Schools:

<?php
$date = "1970-01-01 00:00:00";
$pattern = "/[-\s:]/";
$components = preg_split($pattern, $date);
print_r($components);
?>

Kết quả:

Array ( [0] => 1970 [1] => 01 [2] => 01 [3] => 00 [4] => 00 [5] => 00 )

Bạn có thể thấy mẫu phân cách bao gồm 3 ký tự, hoặc là – hoặc khoảng trắng và cuối cùng là dấu :


Cú pháp tiêu chuẩn của hàm preg_split

Cú pháp:

preg_split(pattern, string, limit, flags)

Giải thích các tham số:

Các tham số Mô tả
pattern Cần phải có. Biểu thức chính quy xác định dấu phân cách được chọn là gì
string Cần phải có. Chuỗi mà chúng ta muốn tách
limit Tùy chọn. Mặc định là -1, nghĩa là không giới hạn. Giới hạn là số phần tử trả về mảng. Nếu giới hạn đạt đến trước khi tất cả phân cách tìm thấy thì phần còn lại của chuỗi sẽ được đưa vào phần tử cuối cùng của mảng
flags Tùy chọn. Các cờ này cung cấp tùy chọn thay đổi mảng trả về:
PREG_SPLIT_NO_EMPTY – Các chuỗi trống sẽ bị loại bỏ khỏi mảng trả về
PREG_SPLIT_DELIM_CAPTURE – Nếu biểu thức chính quy bao gồm được bao trong dấu ngoặc đơn, các kết quả của nhóm này sẽ được đưa vào mảng trả về.
PREG_SPLIT_OFFSET_CAPTURE – Từng phần tử trong mảng trả về sẽ là một mảng với hai phần tử, phần tử đầu là chuỗi con, và phần tử thứ hai là vị trí ký tự đầu tiên của chuỗi con trong chuỗi lớn đầu vào

Ví dụ 3, thử nghiệm với limit:

$str = "dù sao chúng tôi vẫn tin rằng, Novak Djokovic sớm muộn gì cũng sẽ thành tay vợt nắm giữ nhiều danh hiệu nhất";
$pt = '/\s+/';
$rs = preg_split($pt, $str, 12);
print_r($rs);

Kết quả:

Array ( [0] => dù [1] => sao [2] => chúng [3] => tôi [4] => vẫn [5] => tin [6] => rằng, [7] => Novak [8] => Djokovic [9] => sớm [10] => muộn [11] => gì cũng sẽ thành tay vợt nắm giữ nhiều danh hiệu nhất )

Chúng ta có thể thấy đúng như mô tả, nó sẽ tách theo dấu phân cách, và khi đạt đến giới hạn thì chuỗi còn lại được đưa vào phần tử cuối cùng.

Ví dụ 4, thử nghiệm với PREG_SPLIT_OFFSET_CAPTURE :

$str = "dù sao chúng tôi vẫn tin rằng";
$pt = '/\s+/';
$rs = preg_split($pt, $str, -1, PREG_SPLIT_OFFSET_CAPTURE);
print_r($rs);

Kết quả:

Array ( [0] => Array ( [0] => dù [1] => 0 ) [1] => Array ( [0] => sao [1] => 4 ) [2] => Array ( [0] => chúng [1] => 8 ) [3] => Array ( [0] => tôi [1] => 15 ) [4] => Array ( [0] => vẫn [1] => 20 ) [5] => Array ( [0] => tin [1] => 26 ) [6] => Array ( [0] => rằng [1] => 30 ) )

Ở đây chúng ta thấy kết quả trả về như mô tả, tuy nhiên một lần nữa chữ cái mang có dấu tiếng Việt ảnh hưởng đến kết quả, vị trí báo bị tăng thêm vài đơn vị phụ thuộc vào việc chữ cái có dấu hay không.

Ví dụ 5, thử nghiệm với PREG_SPLIT_NO_EMPTY, trước tiên chúng ta sẽ xem nếu không có cờ này thì kết quả sẽ như thế nào:

$str = "nguyễn đức anh";
$rs = preg_split('//u', $str, -1);
print_r($rs);

Đây là hàm tách ký tự mà có khả năng bạn rất thường dùng. Chúng ta cần để //u để nó tách đúng ký tự tiếng Việt.

Kết quả:

Array ( [0] => [1] => n [2] => g [3] => u [4] => y [5] => ễ [6] => n [7] => [8] => đ [9] => ứ [10] => c [11] => [12] => a [13] => n [14] => h [15] => )

Ở đây chúng ta thấy mảng trả về có thêm 3 chuỗi rỗng ở vị trí 0, 11 và 15.

Khi chúng ta dùng PREG_SPLIT_NO_EMPTY:

$str = "nguyễn đức anh";
$rs = preg_split('//u', $str, -1, PREG_SPLIT_NO_EMPTY);
print_r($rs);

Kết quả:

Array ( [0] => n [1] => g [2] => u [3] => y [4] => ễ [5] => n [6] => [7] => đ [8] => ứ [9] => c [10] => [11] => a [12] => n [13] => h )

Thật kỳ lạ, mặc dù nó đã loại bỏ chuỗi rỗng ở các vị trí 0, 11, và 15, nhưng chuỗi rỗng ở vị trí 10, tức là giữa từ “đức” và từ “anh” thì lại không bị loại, mặc dù theo dự trù của chúng ta là nó sẽ bị loại.

Ngay cả khi tôi thử với từ không dấu, và lệnh phân cách bỏ u (vì không dấu thì không cần phải chỉ định utf-8) thì kết quả vẫn vậy.

$str = "nguyen duc anh";
$rs = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY);
print_r($rs);