Highlight the Word in the String, If It Contains the Keyword

highlight the word in the string, if it contains the keyword

Try this:

preg_replace("/\w*?$keyword\w*/i", "<b>$0</b>", $str)

\w*? matches any word characters before the keyword (as least as possible) and \w* any word characters after the keyword.

And I recommend you to use preg_quote to escape the keyword:

preg_replace("/\w*?".preg_quote($keyword)."\w*/i", "<b>$0</b>", $str)

For Unicode support, use the u flag and \p{L} instead of \w:

preg_replace("/\p{L}*?".preg_quote($keyword)."\p{L}*/ui", "<b>$0</b>", $str)

highlight multiple keywords in search

regular expressions is the way to go!

function highlight($text, $words) {
preg_match_all('~\w+~', $words, $m);
if(!$m)
return $text;
$re = '~\\b(' . implode('|', $m[0]) . ')\\b~';
return preg_replace($re, '<b>$0</b>', $text);
}

$text = '
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat.
';

$words = 'ipsum labore';

print highlight($text, $words);

To match in a case-insensitive manner, add 'i' to the regular expression

    $re = '~\\b(' . implode('|', $m[0]) . ')\\b~i';

NB: for non-enlish letters like "ä" the results may vary depending on the locale.

Python highlight each word if text contains combination of words

Inside your replacement function, you can do other regex:

import re

text = 'Just for testing, it is fantastic. Lets do it. Cmon'
keywords = ['testing', 'is fantastic']

def highlight(text, keywords):
replacement = lambda match: re.sub(r'([^\s]+)', r'<mark>\1</mark>', match.group())
text = re.sub("|".join(map(re.escape, keywords)), replacement, text, flags=re.I)
print(text)

highlight(text, keywords)

Prints:

Just for <mark>testing</mark>, it <mark>is</mark> <mark>fantastic</mark>. Lets do it. Cmon

Highlight a word if a string contains that word in jinja2

Inside your flask route where you receive the sentence you could replace the word template with <mark>template</mark>

The HTML element represents text which is marked or highlighted for reference or notation purposes, due to the marked passage's relevance or importance in the enclosing context.

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/mark

Example:

from flask import Flask, render_template
from markupsafe import Markup

app = Flask(__name__)

@app.route("/")
def index():
sentence = "Jinja is a fast, expressive, extensible templating engine. Special placeholders in the template allow writing code similar to Python syntax. Then the template is passed data to render the final document."
data = {"sentence": Markup(sentence.replace("template", "<mark>template</mark>"))}
return render_template("index.html", data=data)

if __name__ == "__main__":
app.run()

You can still add the class to the mark tag if you want to change the default background-color.


The same approach can also be done with Javascript:

document.body.innerHTML = document.body.innerHTML.replaceAll(
"template",
"<mark>template</mark>"
);

You could put this somewhere inside some script tags in the template.


In case the DOM hasn't loaded yet and the above doesn't work try:

window.addEventListener("load", function () {
document.body.innerHTML = document.body.innerHTML.replaceAll(
"{{word}}",
"<mark>{{word}}</mark>"
);
});

For more info on this, see this post.

highlight search keywords in text

Use a HTML parser to make sure that you only search through text.

Highlight Specific Word in Associated String and String Variable in Tableau

As I am sure you know, Tableau is going to colour the entire text string as the CONTAINS condition results in TRUE for the entire string. A different approach could be to restructure your data to a 'long' format with 1 row per word (as below).

Example Data Structure

Doing this will ensure that Tableau knows each word should be evaluated separately and that the Color Marks Card will partition each word. You can then structure your worksheet like this. To ensure the words are showing in the correct order, you'll need a calculated field to create a unique row (I have called sort_order right("000000" + str([sentence_id]),7) + right("000000" + str([Position]), 7). Note that the Text Marks Card is sorted by sort_order and also that the order in which you drag on/order the Mark Cards is important

Tableau Example

The colour_keyword formula then is simply something like [word] = [Keyword Parameter] (maybe check for upper/lowercase variants).

I would recommend maintaining your original table's data structure as well as this 'long table format and link the two datasources via a Relationship (Data > Edit Relationships) and use Dashboard Actions. This would hopefully satisfy your highlight requirements and mean less rework for your other worksheets.

I've published the demo tableau workbook to tableau public here

Match and highlight keywords from list in a string

If you have an array of search words:

var searches = new [] { "Match", "matches", "list", "text" };

and a string to search:

var text = "Match all matches from the list in text and highlight the matches";

You can combine the words into a regular expression that searches first or second or third, etc, by combining them with String.Join (The \b denotes a word boundary so only whole words match):

var regex = @"\b(" + String.Join("|", searches) + @")\b";
// regex: \b(Match|matches|list|text)\b

Then it's a simple matter of applying the search and using a replace to highlight (in a replace expression, $1 is a reference to the first matched group, e.g., the word that was found in the original phrase):

var result = Regex.Replace(text, regex, @"**$1**");
// result: **Match** all **matches** from the **list** in **text** and highlight the **matches**

(Code Demo)

Note that this solution works fine for the example you gave, but there are a number of caveats depending on what your real-world scenario looks like:

  • If your search "words" have special characters recognized by Regex, you may have to escape them, e.g., \.,\(, \), etc.
  • The current code example provided above is case-sensitive, so for example Match would not match match.

Highlight keywords in a paragraph

If it contains html (note that this is a pretty robust solution):

$string = '<p>foo<b>bar</b></p>';
$keyword = 'foo';
$dom = new DomDocument();
$dom->loadHtml($string);
$xpath = new DomXpath($dom);
$elements = $xpath->query('//*[contains(.,"'.$keyword.'")]');
foreach ($elements as $element) {
foreach ($element->childNodes as $child) {
if (!$child instanceof DomText) continue;
$fragment = $dom->createDocumentFragment();
$text = $child->textContent;
$stubs = array();
while (($pos = stripos($text, $keyword)) !== false) {
$fragment->appendChild(new DomText(substr($text, 0, $pos)));
$word = substr($text, $pos, strlen($keyword));
$highlight = $dom->createElement('span');
$highlight->appendChild(new DomText($word));
$highlight->setAttribute('class', 'highlight');
$fragment->appendChild($highlight);
$text = substr($text, $pos + strlen($keyword));
}
if (!empty($text)) $fragment->appendChild(new DomText($text));
$element->replaceChild($fragment, $child);
}
}
$string = $dom->saveXml($dom->getElementsByTagName('body')->item(0)->firstChild);

Results in:

<p><span class="highlight">foo</span><b>bar</b></p>

And with:

$string = '<body><p>foobarbaz<b>bar</b></p></body>';
$keyword = 'bar';

You get (broken onto multiple lines for readability):

<p>foo
<span class="highlight">bar</span>
baz
<b>
<span class="highlight">bar</span>
</b>
</p>

Beware of non-dom solutions (like regex or str_replace) since highlighting something like "div" has a tendency of completely destroying your HTML... This will only ever "highlight" strings in the body, never inside of a tag...


Edit Since you want Google style results, here's one way of doing it:

function getKeywordStubs($string, array $keywords, $maxStubSize = 10) {
$dom = new DomDocument();
$dom->loadHtml($string);
$xpath = new DomXpath($dom);
$results = array();
$maxStubHalf = ceil($maxStubSize / 2);
foreach ($keywords as $keyword) {
$elements = $xpath->query('//*[contains(.,"'.$keyword.'")]');
$replace = '<span class="highlight">'.$keyword.'</span>';
foreach ($elements as $element) {
$stub = $element->textContent;
$regex = '#^.*?((\w*\W*){'.
$maxStubHalf.'})('.
preg_quote($keyword, '#').
')((\w*\W*){'.
$maxStubHalf.'}).*?$#ims';
preg_match($regex, $stub, $match);
var_dump($regex, $match);
$stub = preg_replace($regex, '\\1\\3\\4', $stub);
$stub = str_ireplace($keyword, $replace, $stub);
$results[] = $stub;
}
}
$results = array_unique($results);
return $results;
}

Ok, so what that does is return an array of matches with $maxStubSize words around it (namely up to half that number before, and half after)...

So, given a string:

<p>a whole 
<b>bunch of</b> text
<a>here for</a>
us to foo bar baz replace out from this string
<b>bar</b>
</p>

Calling getKeywordStubs($string, array('bar', 'bunch')) will result in:

array(4) {
[0]=>
string(75) "here for us to foo <span class="highlight">bar</span> baz replace out from "
[3]=>
string(34) "<span class="highlight">bar</span>"
[4]=>
string(62) "a whole <span class="highlight">bunch</span> of text here for "
[7]=>
string(39) "<span class="highlight">bunch</span> of"
}

So, then you could build your result blurb by sorting the list by strlen and then picking the two longest matches... (assuming php 5.3+):

usort($results, function($str1, $str2) { 
return strlen($str2) - strlen($str1);
});
$description = implode('...', array_slice($results, 0, 2));

Which results in:

here for us to foo <span class="highlight">bar</span> baz replace out...a whole <span class="highlight">bunch</span> of text here for 

I hope that helps... (I do feel this is a bit... bloated... I'm sure there are better ways to do this, but here's one way)...



Related Topics



Leave a reply



Submit