最近遇到了一個匹配中文特定字符串的問題,記錄下來
問題描述:匹配“美麗鄉村”中的一個字符或幾個,如果是多個字符,順序不能改變,如“麗鄉”
解決過程:
之前知道匹配中文字符串,正則表達式中使用的是unicode編碼的范圍,如/^[x{4e00}-x{9fa5}]+$/u
想着特定字符是否可以不用轉換成unicode編碼,於是寫出正則 '/^[美]{0,1}[麗]{0,1}[鄉]{0,1}[村}]{0,1}$/u',總不能正確匹配
於是把漢字改成unicode編碼,正則 /^[\x{7f8e}]{0,1}[\x{4e3d}]{0,1}[\x{4e61}]{0,1}[\x{6751}]{0,1}$/u 匹配成功
轉換unicode編碼的函數,一開始用unicode_encode,在我的筆記本上可以正常匹配,但是到公司一試,竟然不能正常匹配,於是把"美"字的unicode編碼打印出來,
居然是“8e7f”,兩個字節顛倒了,百度了一下,原來是unicode編碼有大端小端,用兩個字節表示,用大端編碼時,要把低位數據是字符編碼的高字節,高字節是字符編碼的高字節。
於是改用utf8StrToUnicode,成功解決。
function unicode_encode($str, $encoding = 'UTF-8', $prefix = '[\x{', $postfix = '}]{0,1}') {
$str = iconv($encoding, 'UCS-2', $str);
$arrstr = str_split($str, 2);
$unistr = '';
for($i = 0, $len = count($arrstr); $i < $len; $i++) {
$dec = bin2hex($arrstr[$i]);
$unistr .= $prefix . $dec . $postfix;
}
return $unistr;
}
function utf8StrToUnicode($str ,$prefix = '[\x{', $postfix = '}]{0,1}') {
$strLen = mb_strlen($str);
$uniStr = '';
for($i = 0;$i<$strLen;$i++){
$unicode = 0;
$subStr = mb_substr($str,$i,1);
$unicode = (ord($subStr[0]) & 0x1F) << 12;
$unicode |= (ord($subStr[1]) & 0x3F) << 6;
$unicode |= (ord($subStr[2]) & 0x3F);
$uniStr .= $prefix . dechex($unicode) . $postfix;
}
$uniStr = '/^'.$uniStr.'$/u';
return $uniStr;
}
