需要用 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" 是小写字母(oldword1
、oldword2
)并且如果 "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);
...
我在 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" 是小写字母(oldword1
、oldword2
)并且如果 "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);
...