使用str_ireplace()高亮显示文本


Highlighting text with str_ireplace()

我有一个有趣的问题,我使用PHP的str_ireplace()突出显示关键字数组中的文本。

假设这是我想从示例文本中突出显示的一组关键字或短语:

$keywords = array('eggs', 'green eggs');

这是我的示例文本:

$text = 'Green eggs and ham.';

以下是我如何突出显示文本:

$counter = 0;
foreach ($keywords as $keyword) {
    $text = str_ireplace($keyword, '<span class="highlight_'.($counter%5).'">'.$keyword.'</span>', $text);
    $counter++;
}

这样做的问题是green eggs永远不会得到匹配,因为eggs在文本中已经被替换为:

Green <span class="highlight_0">eggs</span> and ham.

也可能存在部分重叠的情况,例如:

$keywords = array('green eggs', 'eggs and'); 

解决这类问题的明智方法是什么?

反转顺序:

$keywords = array('green eggs', 'eggs');

最简单的方法是先处理最长的字符串,然后再处理较短的字符串。只要确保你不会在同一个字符串上加倍(如果重要的话)。

也许这不是最漂亮的解决方案,但您可以跟踪关键字出现的位置,然后找到它们重叠的位置,并调整您想要包含跨度标签的位置

$keywords = array('eggs', 'n eggs a', 'eggs and','green eg');
$text = 'Green eggs and ham.';
$counter = 0;
$idx_array = array();
$idx_array_last = array();
foreach ($keywords as $keyword) {
    $idx_array_first[$counter] = stripos($text, $keyword);
    $idx_array_last[$counter] = $idx_array_first[$counter] + strlen($keyword);
    $counter++;
}
//combine the overlapping indices
for ($i=0; $i<$counter; $i++) {
    for ($j=$counter-1; $j>=$i+1; $j--) {
        if (($idx_array_first[$i] <= $idx_array_first[$j] && $idx_array_first[$j] <= $idx_array_last[$i]) 
                || ($idx_array_last[$i] >= $idx_array_last[$j] && $idx_array_first[$i] <= $idx_array_last[$j])
                || ($idx_array_first[$j] <= $idx_array_first[$i] && $idx_array_last[$i] <= $idx_array_last[$j])) {
            $idx_array_first[$i] = min($idx_array_first[$i],$idx_array_first[$j]);
            $idx_array_last[$i] = max($idx_array_last[$i],$idx_array_last[$j]);
            $counter--;
            unset($idx_array_first[$j],$idx_array_last[$j]);
        }
    }
}
array_multisort($idx_array_first,$idx_array_last); //sort so that span tags are inserted at last indices first
for ($i=$counter-1; $i>=0; $i--) {
    //add span tags at locations of indices
    $textnew = substr($text,0,$idx_array_first[$i]).'<span class="highlight_'.$i.'">';
    $textnew .=substr($text,$idx_array_first[$i],$idx_array_first[$i]+$idx_array_last[$i]);
    $textnew .='</span>'.substr($text,$idx_array_last[$i]);
    $text = $textnew;
}

输出为

<span class="highlight_0">Green eggs and</span> ham.