У меня есть эта функция, которая использует preg_replace_callback, чтобы разбить предложение на «цепочки» блоков, принадлежащих к разным категориям (буквенные символы, символы хана, все остальное).
Функция пытается также включить символы ‘ , { , а также } как «буквенный»
function String_SplitSentence($string)
{
$res = array();
preg_replace_callback("~\b(?<han>\p{Han}+)\b|\b(?<alpha>[a-zA-Z0-9{}']+)\b|(?<other>[^\p{Han}A-Za-z0-9\s]+)~su",
function($m) use (&$res)
{
if (!empty($m["han"]))
{
$t = array("type" => "han", "text" => $m["han"]);
array_push($res,$t);
}
else if (!empty($m["alpha"]))
{
$t = array("type" => "alpha", "text" => $m["alpha"]);
array_push($res, $t);
}
else if (!empty($m["other"]))
{
$t = array("type" => "other", "text" => $m["other"]);
array_push($res, $t);
}
},
$string);
return $res;
}
Однако что-то не так с фигурными скобками.
print_r(String_SplitSentence("Many cats{1}, several rats{2}"));
Как видно из выходных данных, функция обрабатывает {как буквенный символ, как указано, но останавливается на}, и вместо этого обрабатывает его как «другой».
Array
(
[0] => Array
(
[type] => alpha
[text] => Many
)
[1] => Array
(
[type] => alpha
[text] => cats{1
)
[2] => Array
(
[type] => other
[text] => },
)
[3] => Array
(
[type] => alpha
[text] => several
)
[4] => Array
(
[type] => alpha
[text] => rats{2
)
[5] => Array
(
[type] => other
[text] => }
)
Что я делаю неправильно?
Я не могу быть полностью уверен, потому что ваш пример ввода не представляет никаких китайских символов, и я не знаю, какие дополнительные случаи вы можете пытаться обработать, но вот как я бы написал шаблон:
~(?<han>\p{Han}+)|(?<alpha>[a-z\d{}']+)|(?<other>\S+)~ui
Беда с \b
это то, что он ищет \w
персонажи. \w
представляет заглавные буквы, строчные буквы, цифры и подчеркивания. Ссылка: https://stackoverflow.com/a/11874899/2943403
Также ваш шаблон не включает в себя .
с, чтобы вы могли удалить s
Модификатор
Также ваш вызов функции, кажется, злоупотребляет preg_replace_callback()
, Я имею в виду, вы на самом деле ничего не заменяете, так что это неуместный звонок. Возможно, вы могли бы рассмотреть это переписать:
function String_SplitSentence($string){
if(!preg_match_all("~(?<han>\p{Han}+)|(?<alpha>[a-z\d{}']+)|(?<other>\S+)~ui",$string,$out)){
return []; // or $string or false
}else{
foreach($out as $group_key=>$group){
if(!is_numeric($group_key)){ // disregard the indexed groups (which are unavoidably generated)
foreach($group as $i=>$v){
if(strlen($v)){ // only store the value in the subarray that has a string length
$res[$i]=['type'=>$group_key,'text'=>$v];
}
}
}
}
ksort($res);
return $res;
}
}
Демонстрация о вашей модели: https://regex101.com/r/6EUaSM/1
\ b после того, как ваш класс персонажей запутался. }
не входит в \w
учебный класс. Regex хочет сделать хорошую работу для вас — он захватил «жадно», пока не может больше. }
из-за границы слова.
Других решений пока нет …