我有一个单词数组,用于突出显示字符串中的单词,但是有些单词可能会作为短语的一部分出现,因此我希望该短语优先于突出显示中的单个单词:
例如:
$seo = ['apple', 'apple tree', 'orchard'];
$description = "In my orchard I have a large Apple Tree";
想要的效果:
In my <strong>orchard</strong> I have a large <strong>Apple Tree</strong>
在我自己的第一次尝试中,我循环遍历了针对字符串运行
preg_replace()
的数组,但我得到了像这样的嵌套突出显示 <strong><strong>Apple</strong> Tree</strong>
。
首先,您不应该使用循环来单独替换每个单词,而应该使用正则表达式替代列表
(foo|bar|thingy)
。
$rx_words = implode("|", array_map("preg_quote", $words));
$text = preg_replace("/\b($rx_words)\b/i",
(实际上 preg_quote 缺少第二个参数,但只要关键字中没有正斜杠,它就可以工作。)
然后你还可以通过断言使其更安全:
$text = preg_replace("/(?<!<strong>)\b($rx_words)\b/i",
所以它会忽略已经换行的单词。这只是一种解决方法,但通常就足够了。
在调用
preg_replace()
之前,按长度降序对可替换单词数组进行排序。这将确保较长的字符串在较短的单词之前匹配,从而避免您遇到的嵌套替换问题。
代码:(演示)
$seo = ['apple', 'apple tree', 'orchard'];
$description = "In my orchard I have a large Apple Tree";
array_multisort(array_map('strlen', $seo), SORT_DESC, $seo);
var_export(
preg_replace(
'#\b(?:' . implode('|', $seo) . ')\b#i',
'<strong>$0</strong>',
$description
)
);