Regex problem


$string = "the man has a large wingspan";
$words = array("man","span");

foreach ($words as $word){
    /*** quote the text for rejex ***/
    $word = preg_quote($word);
    /*** highlight the words ***/

    if( !preg_match( '/<(.*)>/', preg_match("/($word)/i",$string) ) ) {
        $string = preg_replace("/($word)/i", '<span     class="highlight">\\1</span>', $string);
    }

}

I’m having some issues trying to highlight some search results.
I am highlighting the words that a user searches. The code iterates through each word in the array and then redefines the string to include a span with a class attribute added to it. The problem is whenever a partial match is made on a subsequent iteration there is a chance that that match is inbetween the html tags.

For example with the above code

Input: the man has a large wingspan
Output:


the <<span class="highlight">span</span> class="highlight">man</<span class="highlight">span</span>> has a large wingspan

Desired Output



the <span class="highlight">man has a large wing<span class="highlight">span</span>

Basically I want to find the regex expression that will allow me to find

“<” & (any number of char) & $word & (any number of char) & “>”

I’ve changed my if statement to

		if( (!preg_match( '/<(.*?)\\b(.*?)($word)(.*?)<\\/(.*?)>/', $string))){

but it’s not working as expected yet, any suggestions on highlighting search terms without highlighting html mark up?

You don’t need regex for this. I’d suggest to use [fphp]strtr[/fphp] instead.


$string = "the man has a large wingspan";
$words = array("man","span");

$trans=array();
foreach($words as $word) {
  $tr[$word]='<span class="highlight">'.$word.'</span>';
}

$string=strtr($string, $trans);

:slight_smile:

There is good news and bad news.

The good news is that strtr(); searches for partial words so that if the word is “Hippo” it will highlight “Hip” if the search string is “hip”

Unfortunately I have the same problem as before. It replaces the “span” that is present in the html tag instead of just the span present in the word “wingspan”

I attached the file below so that you can see for yourself what the output is.




<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>

	<head>
		<style type="text/css">
			.highlight{
				font-weight: bold; 
				color:red;
			}
		</style>
	</head>

	<body>
	
	<?php 
	//*** First Test Checks if it replaces span in html tags
		echo highlight('the man has a <span class="highlight">large</span> wingspan', "man span HA");
		echo "<br /><br /><br /> 2:";
	//***Second checks to see if the removal of span from wingspan makes it work
		echo highlight('the man has a large wing', "man span HA");
	?>
	</body>

</html>

<?php
	function highlight($string, $search){
		/*** Split search string into arrays of words***/
		$words = explode(" ", $search);
$trans=array();
		/*** Go through all the words ***/
		foreach ($words as $word){
			/*** quote the text for rejex ***/
//			$word = preg_quote($word);
			/*** highlight the words ***/
$trans[$word]='<span class="highlight">'.$word.'</span>';
$string=strtr($string, $trans);
	//	if( !preg_match( '/<(.*)>/', preg_match("/($word)/i",$string) ) ) {
	//	if( !preg_match( '/<span\\b[^>]*>(.*?)($word)(.*?)<\\/span>/', $string) ){
//		if( (!preg_match( '/<(.*?)\\b(.*?)($word)(.*?)<\\/(.*?)>/', $string))){
//		echo "here";
//				$string = preg_replace("/($word)/i", '<span //class="highlight">\\1</span>', $string);
//			}
		}
		/*** Return String ***/
		return $string;
	}
?>

Output 1:

the <<span class=“highlight”>spanspan> class=“highlight”><span class=“highlight”>manspan>span class=“highlight”>spanspan>> has a <<span class=“highlight”>spanspan> class=“highlight”>largespan class=“highlight”>spanspan>> wing<span class=“highlight”>spanspan>

Oh… Is there a way to make it case insensitive too?

Taking HTML into account is extremely complicated and basically means you’d have to write a full blown HTML parser in order to it.
This would a take a few hours, if not days.

I looked around a bit, and found this: http://planetcakephp.org/aggregator/items/1627-highlighting-a-search-string-in-html-text

The function introduced and explained there should do what you want

:google: FTW :cool:

Well, I don’t really understand how it works, mainly because I am just staring at it with a blank face but change a few lines here to split the needle into separate search terms and by golly it’s perfect. Thanks, this is exactly what I wanted.