需要用 Unicode 改变 PHP preg_replace_callback 西里尔字母

Need altering PHP preg_replace_callback with Unicode for Cyrillic

我在 PHP 上有以下代码:

$oldstring = 'oldword1, oldword2. Oldword1. Oldword2. OLDWORD1. OLDWORD2';
$results = array(array('old'=>'oldword1', 'new'=>'newword1'), array('old'=>'oldword2', 'new'=>'newword2'));
foreach ($results as $row) {
    $fndrep[$row['old']] = $row['new'];
}

$pattern = '~(?=([A-Z]?)([a-z]?))\b(?i)(?:'
         . implode('|', array_keys($fndrep))
         . ')\b~';

$newstring = preg_replace_callback($pattern, function ($m) use ($fndrep) {
    $lowm = $fndrep[strtolower($m[0])];
    if ($m[1])
        return ($m[2]) ? ucfirst($lowm) : strtoupper($lowm);
    else
        return $lowm;
}, $oldstring);

echo $newstring;

如您所见,它用新词替换了所有旧词。在该结果数组中必须包含仅以小写形式替换的单词。如果 "oldword" 是小写字母(oldword1,oldword2)或大写字母(Oldword1,Oldword2),它对拉丁字符非常有效或大写(OLDWORD1、OLDWORD2)。但我需要西里尔字母的相同解决方案。

如果我改变

$pattern = '~(?=([A-Z]?)([a-z]?))\b(?i)(?:'

到 Unicode

$pattern = '~(?=([\x{0410}-\x{042F}]?)([\x{0430}-\x{044F}]?))\b(?i)(?:'

. ')\b~';

. ')\b~u';

它也适用于西里尔字母,但前提是 "oldword" 是小写字母(oldword1oldword2)并且如果 "oldword" 是大写字母则不起作用字母 (Oldword1, Oldword2) 或大写 (OLDWORD1, OLDWORD2)

谁能解决这个问题?

我找到了解决办法。事实证明,对于西里尔字母,我们需要使用 mb_strtolower/mb_strtoupper 和更多代码来代替 ucfirst() 函数。我很惊讶没有人注意到它

...
$newstring = preg_replace_callback($pattern, function ($m) use ($fndrep) {
    mb_internal_encoding('UTF-8');
    $lowm = $fndrep[mb_strtolower($m[0])];
    if ($m[1])
        return ($m[2]) ? 
        mb_strtoupper(mb_substr($lowm, 0, 1)) . mb_substr(mb_convert_case($lowm, MB_CASE_LOWER), 1, mb_strlen($lowm))
        : mb_strtoupper($lowm);
    else
        return $lowm;
}, $oldstring);
...