views:

77

answers:

3

This is a slightly modified version of the question here. The difference is I don't the special characters to be included in the bold tags if they are on front or back.

Given a needle and a haystack... I want to put bold tags around the needle. So what regex expression would I use with replace()? I want SPACE to be the delimeter and I want the search to be case insensitive and I want special characters (such as @!#.()) to be ignored in the search

so say the needle is "cow" and the haystack is

cows, at www.cows.com, milk some COWS!

would turn into

<b>cows</b>, at www.cows.com, milk some <b>COWS</b>!

also keywords should be able to have spaces in it so if the keyword is "who is mgmt"...

great band. who. is. mgmt btw?

would turn into

great band. <b>who. is. mgmt</b> btw?

Note the dots in the above

I've got this currently:

function updateHaystack(input, needle) {
    return input.replace(new RegExp('(^|\\s)(' + needle + ')(\\s|$)','ig'), '$1<b>$2</b>$3');
}

unfortunately it doesn't bold words that are concatenated with a special char... eg. !cow does not turn into !<b>cow</b>

Thank you

A: 

Just create a class containing your special characters before and after the needle:

function updateHaystack(input, needle) {
  var re = new RegExp('(^|\\s|[!@#,])(' + needle + ')([!@#,]|\\s|$)','ig');
  return input.replace(re, '$1<b>$2</b>$3');
}

Notice, however, that if you add the dot (.) to that list, you'll end up matching things like "www.cows.com". If you don't want that to happen, you should narrow your question.

Also, you should escape the needle if it contains characters that have a meaning in the RegExp, such as the dot (.) or asterisk (_*_).

Sinan Taifour
A: 

Maybe regular expressions are not what you need. If you seek pattern matching where the patterns themselves (the "cow") are not regular expressions on their own, try using a pattern matching algorithm.

You can use KMP (Knuth-Moriss-Pratt if you only have one pattern to find (implementation example curtusy of Google) or AC (Aho-Corasick) if you have more than one pattern to find at the same time and want to be extremely efficient (otherwise you can just run KMP several times).

Aviad Ben Dov
A: 

Here's my solution:

function boldNeedle(needle, haystack) {
    var regex = RegExp("\\b(" + needle.replace(/[-[\]{}()*+?.\\^$|,#\s]/g, "\\$&") + ")\\b", "gi");
    return haystack.replace(regex, "<strong>$1</strong>");
};

boldNeedle("foo", "blah blah FOO blah foo blah")
===
"blah blah <strong>FOO</strong> blah <strong>foo</strong> blah"

Edit: I should explain how this is different from the other solution: It escapes the needle so no part of it is treated as a regular expression.

Eli Grey