在 PHP 中,我需要突出显示字符串中的多个给定单词,例如将找到的匹配项包装在
<em>
标签内。
但如果我有一个以 +
结尾的单词,我就做不到。
我理解下面的问题是 plus 不是一个单词,并且破坏了
\b
标志单词匹配。但是我怎样才能写这个,以便它匹配并包装所有给定的单词,即使给定的单词以 +
结尾?
$my_text = 'test c+ and javascript etc but NOT javascripter';
$words_to_highlight = array('javascript', 'c+');
foreach($words_to_highlight as $word){
$search_pattern = str_replace('+', '\\+', $word);
// this doesn't match replacement
echo "\n".preg_replace("/\b(".$search_pattern.")\b/i", '<em>$1</em>', $my_text);
// works if I remove the \b flag, but I don't want to match "javascript" inside "javascripter"
echo "\n".preg_replace("/(".$search_pattern.")/i", '<em>$1</em>', $my_text);
}
输出是:
test c+ and <em>javascript</em> etc but NOT javascripter
test c+ and <em>javascript</em> etc but NOT <em>javascript</em>er
test c+ and javascript etc but NOT javascripter
test <em>c+</em> and javascript etc but NOT javascripter
我想要的结果是:
test <em>c+</em> and <em>javascript</em> etc but NOT javascripter
您可以使用环视形式的空白边界,而不是使用单词边界,断言左侧和右侧不是非空白字符。
对于正则表达式语法中的转义字符,您可以使用 preg_quote。
为了一次性替换,您可以使用列出所有替代方案的非捕获组动态创建正则表达式。
最终的图案如下所示:
(?<!\S)(?:javascript|c\+)(?!\S)
例如:
$my_text = 'test c+ and javascript etc but NOT javascripter';
$words_to_highlight = array('javascript', 'c+');
$pattern = sprintf(
"/(?<!\S)(?:%s)(?!\S)/i",
implode('|', array_map("preg_quote", $words_to_highlight))
);
echo preg_replace($pattern, '<em>$0</em>', $my_text);
输出
test <em>c+</em> and <em>javascript</em> etc but NOT javascripter