I am searching a text (plain text) for keywords and key phrases. I want to highlight them by wrapping them in a span
-tag. This part works. However I want to avoide highlighting words that are already highlighted (i.e. already wrapped in a span-tag)
I found this solution that shows a very nice way to do this: Match text not inside span tags
However I'm trying to do this in PHP and have been trying to convert the example from the above question to PHP:
var subject = 'Red apples are my <span class="highlight">favourite apples.</span>';
var regex = /<span.*?<\/span>|(\bapples\b)/g;
replaced = subject.replace(regex, function(m, group1) {
if (group1 == "" ) return m;
else return "<span class=\"highlight\">" + group1 + "</span>";
});
document.write("<br>*** Replacements ***<br>");
document.write(replaced);
I've been at it for a few days wrestling with the preg_*
functions. However I still sit here with nothing to show for. Well I have this working code:
$text = 'Red apples are my <span class="highlight">favourite fruit.</span> <span class="highlight">Red apples are my favourite fruit.</span> I love red apples.';
$pattern = '/<span.*?<\/span>|(\bapples\b)/i';
preg_match_all($pattern, $text, $matches);
print_r($matches[0]);
print_r($matches[1]);
which outputs
Array ( [0] => apples [1] => favourite fruit. [2] => Red apples are my favourite fruit. [3] => apples )
Array ( [0] => apples [1] => [2] => [3] => apples )
telling me that the RegEx works. How to replace only on the second group like in the above JavaScript example I simply cannot figure out.
Any help getting the above javascript example working in PHP would be appriciated. Hoping to learn more about the PHP regex functions while at it.
*** SOLUTION ***
All credits to @SashaKondrashov for providing this solution:
$text = 'Red apples are my <span class="highlight">favourite fruit.</span> <span class="highlight">Red apples are my favourite fruit.</span> I love red apples.';
$pattern = '/<span.*?<\/span>|(\bapples\b)/i';
$result = preg_replace_callback($pattern, function ($matches) {
if (count($matches) == 1) return $matches[0];
return "<span>{$matches[1]}</span>";
}, $text);
print_r($result);