[英]UTF-8 characters in preg_match_all (PHP)
我有preg_match_all('/[aäeëioöuáéíóú]/u', $in, $out, PREG_OFFSET_CAPTURE);
如果$in = 'hëllo'
$out
是:
array(1) {
[0]=>
array(2) {
[0]=>
array(2) {
[0]=>
string(2) "ë"
[1]=>
int(1)
}
[1]=>
array(2) {
[0]=>
string(1) "o"
[1]=>
int(5)
}
}
}
o
的位置應為4。我已經在線閱讀有關此問題的信息( ë
被計為2)。 有解決方案嗎? 我看過mb_substr
和類似的東西,但是preg_match_all
是否有類似的東西?
相關種類:它們在Python中是否等於preg_match_all
? (返回匹配項及其在字符串中的位置)
這不是錯誤, PREG_OFFSET_CAPTURE
是指字符串中字符的字節偏移量。
mb_ereg_search_pos
行為方式相同。 一種可能是先將編碼更改為UTF-32,然后再將位置除以4(因為在utf-32中所有unicode碼單元都表示為4字節序列):
mb_regex_encoding("UTF-32");
$string = mb_convert_encoding('hëllo', "UTF-32", "UTF-8");
$regex = mb_convert_encoding('[aäeëioöuáéíóú]', "UTF-32", "UTF-8");
mb_ereg_search_init ($string, $regex);
$positions = array();
while ($r = mb_ereg_search_pos()) {
$positions[] = reset($r)/4;
}
print_r($positions);
給出:
Array ( [0] => 1 [1] => 4 )
您也可以將二進制位置轉換為代碼單位位置。 對於UTF-8,次佳的實現是:
function utf8_byte_offset_to_unit($string, $boff) {
$result = 0;
for ($i = 0; $i < $boff; ) {
$result++;
$byte = $string[$i];
$base2 = str_pad(
base_convert((string) ord($byte), 10, 2), 8, "0", STR_PAD_LEFT);
$p = strpos($base2, "0");
if ($p == 0) { $i++; }
elseif ($p <= 4) { $i += $p; }
else { return FALSE; }
}
return $result;
}
有一個簡單的解決方法,可在preg_match()結果匹配后使用。 您需要迭代每個匹配結果,並使用以下方法重新分配位置值:
$utfPosition = mb_strlen(substr($wholeSubjectString, 0, $capturedEntryPosition), 'utf-8');
在Windows下對php 5.4進行了測試,僅取決於Multibyte PHP擴展。
PHP不能很好地支持unicode,因此許多字符串函數(包括preg_ *)仍以字節而不是字符為單位。
我嘗試通過編碼和解碼字符串來找到解決方案,但最終所有歸結為preg_match_all函數。
關於python事情:python regex matchobject默認包含mo.start()和mo.end()的匹配位置。 請參閱: http : //docs.python.org/library/re.html#finding-all-adverbs-and-their-positions
如何通過正則表達式拆分UTF-8 $string
的另一種方法是使用函數preg_split()
。 這是我的工作解決方案:
$result = preg_split('~\[img/\d{1,}/img\]\s?~', $string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
PHP 5.3.17
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.