0

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);
kjaer108
  • 11
  • 2
  • 1
    Do you really want to be in [that hole](https://stackoverflow.com/a/1732454) of parsing HTML with regex? It's not a good idea at all. – InSync Mar 27 '23 at 07:21
  • I will be replaceing within a text without any html but wants to highlight certain keywords and phrases using the span element. So I am not going to parse HTML. Just want to make sure I do not replace words in a text already highlighted. As a side effect I would like to know more about the preg_* functions through this example. – kjaer108 Mar 27 '23 at 07:40
  • I am unsure why this question was marked as a duplicate and closed? The referenced answer does not show how to do this in PHP using the `preg_*` functions (if that's what it takes)? I have edited the text to be more clear. – kjaer108 Mar 27 '23 at 10:16
  • I think you might be looking for preg_replace_callback() ? – Sasha Kondrashov Mar 27 '23 at 10:57
  • @kjaer108 I was able to get it I think: https://onlinephp.io/c/383e . I don't think this question should have been closed, the alleged duplicate question has almost exclusively regex answers, and the one answer with a PHP function has no explanation for the answer at all. Wouldn't be surprised if there was a different duplicate but this is a PHP question and the other one is a regex question. If this gets re-opened feel free to steal the fiddle and post it as an answer (whoever). – Sasha Kondrashov Mar 27 '23 at 20:28
  • @SashaKondrashov Unfortunatly your link does not work (Code was not found). Would love to see what you have tried. – kjaer108 Mar 28 '23 at 07:04
  • @kjaer108 My fault, i must have accidentally deleted the last character in the link: https://onlinephp.io/c/383e8 – Sasha Kondrashov Mar 29 '23 at 09:15
  • 1
    @SashaKondrashov Sorry for the late response... Got pulled away from my project for a bit... Well that's it! It works and is amazingly simple. Have to play around with `preg_replace_callback` a bit more... Looks very powerfull. Thank you so much! – kjaer108 Mar 31 '23 at 07:18

0 Answers0