簡體   English   中英

preg_match_all(PHP)中的UTF-8字符

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM