$string = "Here be my string la";
//trim up keywords, and put them into $words array ...
$term = preg_replace('/(\s+)/i', ' ', trim("la"));
$words = explode(' ', $term);
$highlighted = array();
foreach ( $words as $word ){
$highlighted[] = "<span class='H'>".ucwords(htmlentities($word, ENT_NOQUOTES, 'UTF-8'))."</span>";
}
//replace any hits with the highlighted version...
return str_ireplace($words, $highlighted, $string);
It works fine, except if your keyword resembles anything in span class='H' eg 'la'
I understand that it's finding 'la' within the span, and then putting a span around it. What I don't understand is HOW? I figure I'm misunderstanding str_ireplace, but doesn't it say 'if $words[0] is in "string", replace it with $highlighted[0]', and so on through the arrays. How is it finding 'la' in
str[i]_replace are greedy in regards to an array. So it will take the string in its entirety, and check for replacements on EACH iteration of item provided by the array needle.
So if I do like so:
PHP Code:
$aWords = array('cat', 'dog', 'mouse', 'la');
$aHighlight = array();
$str = 'The dog chases the cat which chases the mouse';
The dog chases the cat which chases the mouse <-- evaluate 'cat'
The dog chases the <span class="H">Cat</span> which chases the mouse <-- evaluate 'dog'
The <span class="H">Dog</span> chases the <span class="H">Cat</span> which chases the mouse <-- evaluate 'mouse'
The <span class="H">Dog</span> chases the <span class="H">Cat</span> which chases the <span class="H">Mouse</span> <-- evaluate 'la'
The <span c<span class="H">La</span>ss="H">Dog</span> chases the <span c<span class="H">La</span>ss="H">Cat</span> which chases the <span class="H">La</span> <span c<span class="H">La</span>ss="H">Mouse</span> <-- end result
Because of the purpose of the above, there isn't really a great way to do this with an string match/replace technique (you'll need to keep backtracking and checking new terms).
Instead, simply use pattern matching.
PHP Code:
$str = 'The dog chases the cat which chases the mouse';
Yep you bet. Also, you can check the API here; I didn't realize that they did actually indicate that this would happen (check the caution note just before the user comments): http://ca2.php.net/manual/en/function.str-replace.php
It might be of interest because it uses functions and it can be modified to use different colours for different (arrays of) words:
PHP Code:
function codeWords($code, $colour) // ... array_walk($keywords2, 'addSpan', $colour);
__________________
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
Validate your HTML and CSS
As a newcomer I'm learning a lot from this forum and I've been playing with some of the suggestions on this topic.
Wouldn't something simple like this do the job? Playing with Fou-Lou's latter example I notice that substituting 'concatenation' for 'cat' in $str echos out as "conCatenation". This simple version fixes that and also allows for punctuation to be appended to a keyword.
Code:
echo "<style>.H{color:red;}</style>";
$str = 'The dog chases the cat, which chases the mouse.';
$aWords = array('cat', 'dog', 'mouse', 'la');
$str = explode(' ',$str);
foreach($str as $word){
$remove = array(',', ';', '.'); // ignore common bits of puntuation
$trimmedword = strtolower(str_replace($remove, '', $word));// in case key words are upper case or capitalised
if(in_array($trimmedword,$aWords)){
echo "<span class=H>".ucwords($word)."</span>";
}
else {
echo $word;
}
echo " ";
}
As a newcomer I'm learning a lot from this forum and I've been playing with some of the suggestions on this topic.
Wouldn't something simple like this do the job? Playing with Fou-Lou's latter example I notice that substituting 'concatenation' for 'cat' in $str echos out as "conCatenation". This simple version fixes that and also allows for punctuation to be appended to a keyword.
Code:
echo "<style>.H{color:red;}</style>";
$str = 'The dog chases the cat, which chases the mouse.';
$aWords = array('cat', 'dog', 'mouse', 'la');
$str = explode(' ',$str);
foreach($str as $word){
$remove = array(',', ';', '.'); // ignore common bits of puntuation
$trimmedword = strtolower(str_replace($remove, '', $word));// in case key words are upper case or capitalised
if(in_array($trimmedword,$aWords)){
echo "<span class=H>".ucwords($word)."</span>";
}
else {
echo $word;
}
echo " ";
}
Is this too simple? Am I missing something?
Your right I missed the word boundaries. The pattern can be simply replaced using: $sPattern = '/\b(' . implode('|', $aWords) . ')\b/i';. That will work otherwise as it echos instead of replaces. It will unfortunately replace a space with an , but that's easy enough to get around as well. Since it iterates each term, it will be slow.
Quote:
Originally Posted by AndrewGSW
I did this in a slightly different way and don't know if the following code is of any interest - apologies if not.
PHP Code:
function onlyWholeWords(&$value, $key) { // Ignores words after // comment delimiters. //$value = "/\b(" . $value . ")\b/"; // doesn't handle comments, so.. //$value = "/^(?:(?!\/\/).)*\K\b(" . $value . ")\b/"; // \K lookbehind alternative is not supported in PHP < 5.2.4, so use: $value = "/^((?:(?!\/\/).)*)\b" . $value . "\b/"; } function addSpan(&$value, $key, $color='blue') { $value = "$1<span style='color:$color'>" . $value . "</span>"; } function codeWords($code) { $keywords = array('as', 'break', 'case', 'class', 'continue', 'default', 'do', 'elif', 'else', 'elseif', 'for', 'foreach', 'function', 'if', 'new', 'null', 'return', 'self', 'switch', 'this', 'to', 'typeof', 'until', 'var', 'void', 'while', 'with'); $keywords2 = $keywords;
It might be of interest because it uses functions and it can be modified to use different colours for different (arrays of) words:
PHP Code:
function codeWords($code, $colour) // ... array_walk($keywords2, 'addSpan', $colour);
That's neat, but it still won't work. The problem is that if you use str_replace it will become greedy on each iteration. If you use an array of pattern and replace then they will also be greedy since each evaluation is distinct on the subject. So it would ultimately give the same behaviour as an str_replace. If you change the span style to a span class, then add 'cat' (for concatination ), then you would end up with it replacing both the span to the cat with the class, as well as the class when it hits it further in. It would be useful for C syntax highlight, but not useful for a search highlight (albeit redundant since PHP has a builtin highlight function).
@Fou-Lu Thank you. Actually, I recall now that I'm cheating
PHP Code:
$line = codeWords($line); // blue keywords
$line = str_replace(' ', ' ', $line);
// Use @ to break-up keywords that shouldn't be colour-coded;
// use @@ to keep a single @ sign.
$line = preg_replace('/((\@)(\@)?)/', '$3', $line);
$html_lines .= "<li class=\"tab$count_fours\">$line</li>";
I'm using at @ signs to break words that I wish to exclude. So my example is not directly relevant to the OPs question. Sorry for the confusion .
__________________
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
Validate your HTML and CSS
Mmm, might investigate this, but then again.. I've already done it
__________________
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
Validate your HTML and CSS
Mmm got that page open (highlight_string) but it's just for PHP code..
My approach is for displaying database-content as code in a kindof-blog.
__________________
"I'm here to save your life. But if I'm going to do that, I'll need total uninanonynymity." Me Myself & Irene.
Validate your HTML and CSS
Last edited by AndrewGSW; 12-08-2012 at 05:14 PM..