Php 突出显示给定字符串中的多个匹配项

Php 突出显示给定字符串中的多个匹配项,php,regex,Php,Regex,我在PHP中有一个函数,用于突出显示给定字符串中的搜索词: function highlight_match($h, $text_to_search){ foreach($h as $pattern){ $text_to_search = preg_replace("/($pattern)/i", "<span class=\"highlight_match\">$1</span>", $text_to_search); } r

我在PHP中有一个函数,用于突出显示给定字符串中的搜索词:

 function highlight_match($h, $text_to_search){ 
    foreach($h as $pattern){
        $text_to_search = preg_replace("/($pattern)/i", "<span class=\"highlight_match\">$1</span>", $text_to_search);
    }
    return $text_to_search;
 }    
函数高亮显示匹配($h,$text\u to\u search){
foreach($h作为$pattern){
$text_to_search=preg_replace(“/($pattern)/i”、“$1”、$text_to_search);
}
返回$text\u到\u搜索;
}    
使用这样的函数可以很好地工作:

 $h = array(
     'peter',
     'bell'
 );
 $text_to_search = 'peter pan likes tinker bell'
 echo highlight_match($h, $text_to_search);
 // results: <span class="highlight_match">peter</span> pan likes tinker <span class="highlight_match">bell</span>
$h=数组(
“彼得”,
“贝尔”
);
$text\u to\u search='peter pan喜欢小叮当'
回声突出显示匹配($h,$text\u to\u search);
//结果:彼得潘喜欢小叮当
当搜索词包含在上一次迭代中刚刚替换(添加)的部分内容时,就会出现问题,如以下示例所示:

 $h = array(
     'pan',
     'bell'
 );
 $text_to_search = 'peter pan likes tinker bell'
 echo highlight_match($h, $text_to_search);
 // results: peter <s<span class="highlight_match">pan</span> class="highlight_match">pan</s<span class="highlight_match">pan</span>> likes tinker <span class="highlight_match">bell</span>
$h=数组(
"潘",,
“贝尔”
);
$text\u to\u search='peter pan喜欢小叮当'
回声突出显示匹配($h,$text\u to\u search);
//结果:彼得潘喜欢小叮当
这是因为函数正在迭代要查找的术语列表,因此第二次+迭代可以有。。文本,如果当前迭代的搜索词与给定字符串中的任何内容匹配(包括我们在上一次迭代中刚刚添加的任何文本/html),它将被替换


我不知道如何解决这个问题。是否有一种函数/方法可以同时对字符串进行所有不同的匹配/替换

您可以将所有字符串放在一个模式中:

$highlighted=preg\u replace(
“/(彼得·潘)/i”,
"$1",
$text_to_search);
在这种情况下,模式
(彼得·潘)
表示“彼得或潘”

还有一种解决方案比简单或模式更灵活。如果你真的需要一个接一个地应用你的替代品,它是有效的

它分两步工作:首先,像以前一样替换文本,但不插入
s,而是插入一个与模式不匹配的占位符。在第二步中,将占位符替换为实际的突出显示标记:

$replace=array('pan','bell');
$text_to_search='peter pan喜欢小叮当';
$delim='yB9oMjDWpMy';//只是一个随机字符串;必须与您的模式不匹配
$tags=数组(
“开放式”=>“,
“关闭$delim”=>“
);
foreach($替换为$期限)
{
$text\u to\u search=preg\u replace(
“/($term)/i”,
sprintf('open\u1$s$1close\u1$s',$delim),
$text_to_search);
}
//中间结果:
//彼得·潘喜欢小叮当
$text\u to\u search=str\u replace(
数组_键($tags),
数组_值($tags),
$text_to_search);
//最终结果
//彼得潘喜欢小叮当

这有点复杂,但它允许使用更广泛的regex模式。

如果将组件regexp括起来,第一种方法应该没有问题。匹配总是不重叠的,因此这似乎是更安全的解决方案。