近日遇到一個神奇的字“弢(tao)”。
具體的過程是這樣的:
1 $list = explode('|', 'abc弢|bc');
2 var_dump($list);
取得這個分割的結果。
和想象不同,結果居然是這樣:
array(3) {
[0]=>
string(4) "abc?
[1]=>
string(0) ""
[2]=>
string(2) "bc"
}
出現了亂碼,而且莫名其妙的出現了一個空元素。
究其原因,原來這個字“弢”的gbk編碼是8f7c,而|的ASCII是7c,這樣explode就把弢的第二ASCII作為|切割了。
既然是雙字節的問題,我們用mbstring解決好了。
可惜,php並沒有mb_explode這種函數,找了找,找到一個mb_split。
array mb_split ( string $pattern , string $string [, int $limit = -1 ] )
沒有聲明編碼的地方。仔細一看,他是通過mb_regex_encoding聲明編碼的。
於是寫出以下的代碼:
1 mb_regex_encoding('gbk');
2 $list = mb_split('\|', 'abc弢|bc');
3 var_dump($list);
結果php報錯,mb_regex_encoding不認識gbk,囧。
那就使用它認識的:
1 mb_regex_encoding('gb2312');
2 $list = mb_split('\|', 'abc弢|bc');
3 var_dump($list);
結果:
array(3) {
[0]=>
string(4) "abc?
[1]=>
string(0) ""
[2]=>
string(2) "bc"
}
發現,這種方法並沒有什麼用處。、
至於原因?“弢”這個字居然不在GB2312的編碼集裡面!!!!!但是有這個字的編碼集(GBK, GB18030)這個函數都不支持!!!!!
既然這個不好用,也許萬能的正則表達式是ok的。於是得到以下代碼:
1 var_dump(preg_match_all('/([^\|])*/', 'abc弢|bc', $matches));
2 var_dump($matches);
結果:
int(2)
array(2) {
[0]=>
array(2) {
[0]=>
string(4) "abc?
[1]=>
string(2) "bc"
}
[1]=>
array(2) {
[0]=>
string(1) "?
[1]=>
string(1) "c"
}
}
好吧,我想多了。
現在研究一下,如何用正則描述這個場景。
參考一下,鳥哥大神的博客:分割GBK中文遭遇亂碼的解決。遺憾的是,正則能力比較low的我,還是想不出來合適的正則表達式(如果有想出這個正則表達式的大神們,希望可以告訴我)。
沒辦法,思來想去,只好用substr了:
1 function mb_explode($delimiter, $string, $encoding = null){
2 $list = array();
3 is_null($encoding) && $encoding = mb_internal_encoding();
4 $len = mb_strlen($delimiter, $encoding);
5 while(false !== ($idx = mb_strpos($string, $delimiter, 0, $encoding))){
6 $list[] = mb_substr($string, 0, $idx, $encoding);
7 $string = mb_substr($string, $idx + $len, null, $encoding);
8 }
9 $list[] = $string;
10 return $list;
11 }
測試代碼:
1 $a = 'abc弢|bc';
2
3 var_dump(mb_explode('|', $a, 'gbk'));
4 var_dump(mb_explode('bc', $a, 'gbk'));
5 var_dump(mb_explode('弢', $a, 'gbk'));
結果:
array(2) {
[0]=>
string(5) "abc弢"
[1]=>
string(2) "bc"
}
array(3) {
[0]=>
string(1) "a"
[1]=>
string(3) "弢|"
[2]=>
string(0) ""
}
array(2) {
[0]=>
string(3) "abc"
[1]=>
string(3) "|bc"
}
這樣就可以得到正確的結果了。