Forum Moderators: coopster

Message Too Old, No Replies

regular expression help

         

darkage

6:56 pm on Jul 4, 2007 (gmt 0)

10+ Year Member



When someone searches on my site, i split the search query into tokens and use regular expression to highlight a match in a string.

Example:


$str= eregi_replace("(".quotemeta($tok).")", "<span class=\"genlarge\"><b>\\1</b></span>", $str);

Now the problem is that because this code is looped for each token, searching for "s" will match the "s" in span and highlight that effectively messing it all up.

Therefore i need to replace my code with something like this:

Match all $tokens that are NOT surrounded by <span class="genlarge"><b> ... and </b></span> (because that has already been highlighted)

Any suggestions on how this can be done?

thanks in advance.

pinterface

6:18 am on Jul 5, 2007 (gmt 0)

10+ Year Member



If I understand you correctly, you are basically doing:
    $tokens = ["x", "y", "z"]; 
    foreach ($tokens as $tok)
    $str = eregi_replace("(".quotemeta($tok).")", "<span class=\"genlarge\"><b>\\1</b></span>", $str);
yes?

Regular expressions have the wonderful quality that you can separate alternatives with ¦. For instance, "(x¦y¦z)" will match "x", "y", or "z". How can we use that to our advantage?

Given that we have an array of alternatives, all we need is a function to take those alternatives and join them together with '¦'. Not surprisingly, that function is join.

    [url=http://php.net/join]join[/url]('¦', ['x', 'y', '[zip]']);
    =>
    [i]"x¦y¦[zip]"[/i]
But that's not quite what we want, is it? We already have a function which allows us to quote a string (quotemeta)--if only there was a way to apply that function to every element of an array. That one is called array_map.
    [url=http://php.net/array_map]array_map[/url]('quotemeta', ['x', 'y', '[zip]']);
    =>
    [i]['x', 'y', '\[zip\]'][/i]
Combine the two and we end up with:
    join('¦', array_map('quotemeta', ['x', 'y', '[zip]']));
    =>
    [i]"x¦y¦\[zip\]"[/i]

Note this technique neatly sidesteps trying to come up with a regular expression which avoids matching things inside the tag portion of HTML tags. For that, you'll want to look at PCRE [php.net] for look-ahead and look-behind assertions.

darkage

3:11 pm on Jul 5, 2007 (gmt 0)

10+ Year Member



Hi Pinterface,

You gave me some good leads which ill follow up on tonight.

If i can get all the tokens into one regular expression then i am effectively not highlighting already highlighted items and thus have solved my problem.

Thanks for the help.

darkage

7:54 pm on Jul 5, 2007 (gmt 0)

10+ Year Member



worked perfect!

function highlightSearchTerm($str) {
global $query;

$queryPattern = str_replace(" ", "¦", $query);

$str = eregi_replace("(".quotemeta($queryPattern).")", "<span class=\"genlarge\"><b>\\1</b></span>", $str);

return $str;
}