views:

587

answers:

4

A couple of PHP ereg_replace questions. I have an array of names:

$ssKeywords = array("Str", "Int", "String", "As", "Integer", "Variant");

However when I use this ereg_replace:

foreach($arKeyword as $aWord) {
  $sCode = ereg_replace($aWord, "<span class='ssKeyword'>".$aWord."</span>", $sCode);
}

It will only find the "str" or "int" not the full match. Apparently ereg_replace is greedy, so why is it not looking for the full match?

I managed to get comments working using preg_replace.

+3  A: 

Do you need to use ereg? it has been deprecated and will be obsolete as of PHP 6. I suggest you use preg, which is also more efficient.

This information is available at php.net/ereg

Evernoob
Using this function just causes errors.
James Brooks
Errors' meaning of existence is to be fixed, not to be forgotten by using different function ;)
Max
Well I got comments working! Now just the keywords.
James Brooks
@Max: Two functions exist to accomplish the same task. One of them is misbehaving according to your understanding and officially deprecated. Why wouldn't you use the other function?
Autocracy
+3  A: 

Instead of searching for one term at a time better search for all of them at a time:

$sCode = preg_replace('/(?:'.implode('|', array_map('preg_quote', $ssKeywords)).')/', '<span class="ssKeyword">$0</span>', $sCode);

And if you sort the terms by its length, you will find Integer instead of just Int:

usort($ssKeywords, create_function('$a,$b', 'return strlen($b)-strlen($a);'));
Gumbo
Well the sorting part worked, but the actual replacement didn't.
James Brooks
Ah nevermind, I still had the code in the foreach loop.
James Brooks
+3  A: 

Your problem is nothing to do with ereg_replace. Not only is preg_replace a better bet, but in fact in your case you aren't using any type of regular expressions; you're just doing a plain string match. So str_replace would be quicker and clearer.

The problem is that you're doing:

foreach($arKeyword as $aWord) {

which loops from the first to the last element of the array, testing the whole string against each of the keywords in the order you declared them. You declared ‘Int’ first, so any ‘Integer’ in the string will get replaced by “<span class="ssKeyword">Int</span>eger” before the loop gets as far as the ‘Integer’ keyword. By which time, with the “</span>” in the way, it'll never match.

Change the array order so that the longer keywords come first and it'll work.

bobince
That's a good idea. Shame that I can get this to work fine in JavaScript though. Thanks anyway!
James Brooks
What about case insensitivity?
James Brooks
str_ireplace, possibly. Although if you need case-insensitive-but-preserving, yeah, preg_replace might be the easier route.
bobince
Can you check out Gumbos reply and see why the code times out?
James Brooks
Works for me. It's possible to make a usort comparator function that confuses it, but Gumbo's looks OK as far as I can see.
bobince
Yeah I realised I had his code in the foreach loop - woops!My next task is to stop highlighting in highlighting!
James Brooks
A: 

If you're doing a plain-text match then str_replace is more efficient and less unnecessary. If you do need regular expressions any time in the future, use the preg_* functions because ereg_* is deprecated and preg_* is faster.

With regard to your question about "greedy", that refers to when you're actually using regular expressions. For example if you have the text:

Hello World! Hello World!

And use a regex like this:

/Hell(.+)rld!/

Then it will match the entire string because the + operator is greedy and finds as much as it can on one line. You'd need to do this to stop it being greedy and match each of the phrases:

/Hell(.+?)rld!/
DisgruntledGoat