1

我有这个函数,它利用 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] => }
        )

我究竟做错了什么?

4

1 回答 1

0

我不能完全确定,因为您的示例输入不代表任何汉字,而且我不知道您可能正在尝试处理什么样的边缘案例,但这就是我编写模式的方式:

~(?<han>\p{Han}+)|(?<alpha>[a-z\d{}']+)|(?<other>\S+)~ui

问题\b在于它正在寻找\w字符。 \w代表大写字母、小写字母、数字和下划线。参考:https ://stackoverflow.com/a/11874899/2943403

此外,您的模式不包含任何.s ,因此您可以删除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类中。正则表达式想为您做好工作——它“贪婪地”捕获,直到它不再能捕获。由于单词边界, the}被排除在外。

于 2018-02-12T03:38:43.557 回答