将子字符串包裹在 <strong> 标签中,而无需在替换时创建嵌套标签

问题描述 投票:0回答:2

我有一个单词数组,用于突出显示字符串中的单词,但是有些单词可能会作为短语的一部分出现,因此我希望该短语优先于突出显示中的单个单词:

例如:

$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>

php html arrays preg-replace
2个回答
1
投票

首先,您不应该使用循环来单独替换每个单词,而应该使用正则表达式替代列表

(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",

所以它会忽略已经换行的单词。这只是一种解决方法,但通常就足够了。


0
投票

在调用

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
    )
);
© www.soinside.com 2019 - 2024. All rights reserved.