preg_replace_callback: включая фигурные скобки в шаблоне: {захватывается, } нет
У меня есть эта функция, которая использует 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] => }
)
Что я делаю неправильно?
1 ответ
Я не могу быть полностью уверен, потому что ваш пример ввода не представляет никаких китайских символов, и я не знаю, какие дополнительные случаи вы можете пытаться обработать, но вот как я бы написал шаблон:
~(?<han>\p{Han}+)|(?<alpha>[a-z\d{}']+)|(?<other>\S+)~ui
Беда с \b
это то, что он ищет \w
персонажи. \w
представляет заглавные буквы, строчные буквы, цифры и подчеркивания. Ссылка: /questions/47145192/raznitsa-mezhdu-w-i-b-metasimvolami-regulyarnyih-vyirazhenij/47145249#47145249
Также ваш шаблон не включает в себя .
с, чтобы вы могли удалить 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 хочет сделать хорошую работу для вас - он захватил "жадно", пока не может больше. }
из-за границы слова.