JavaScript/jQuery case indifferent RegEx replace - javascript

I'm trying to figure out how to do a RegEx search on a string that ignores case, but when it does a replacement it should preserve the original case.
i.e.
Searching for "adv" should match "Adv", but the replacement should match "Adv" not "adv"
The purpose is to 'highlight' text in a string. Obviously if there is something easier I'm all ears.
Current code...
$("#SearchResults").append(appendString.replace(
new RegExp($("#SearchInput").val(), "g"), "<strong>" +
$("#SearchInput").val() + "</strong>")
);

You need to encapsulate the value with parenthesis, this will create a group and you will be able the get that group in the replacement string with $n where n is the number of the group. The index start to 1.
So use that :
appendString.replace(new RegExp('(' + $("#SearchInput").val() + ')', "gi"), "<strong>$1</strong>");
Note that using regexp like that is dangerous, for instance, if I write (hello in the input, it will throw an error : invalid regexp.

Karl's approach is right, although you might also need to escape special characters:
var value = $("#SearchInput").val();
var escaped = value.replace(/([\[\]\(\)\/\.\*\+])/g, "\\$1");
// Regex: new RegExp(escaped, "gi");
// Replace with: "<strong>" + value + "</strong>");
Edit for typo.

Related

Javascript (Regex): How do i replace (Backslash + Double Quote) pairs?

In Javascript, i want the below original string:
I want to replace \"this\" and \"that\" words, but NOT the one "here"
.. to become like:
I want to replace ^this^ and ^that^ words, but NOT the one "here"
I tried something like:
var str = 'I want to replace \"this\" and \"that\" words, but NOT the one "here"';
str = str.replace(/\"/g,"^");
console.log( str );
Demo: JSFiddle here.
But still .. the output is:
I want to replace ^this^ and ^that^ words, but NOT the one ^here^
Which means i wanted to replace only the \" occurrences but NOT the " alone. But i cannot.
Please help.
As #adeneo's comment, your string was created wrong and not exactly like your expectation. Please try this:
var str = 'I want to replace \\"this\\" and \\"that\\" words, but not the one "here"';
str = str.replace(/\\\"/g,"^");
console.log(str);
You can use RegExp /(")/, String.prototype.lastIndexOf(), String.prototype.slice() to check if matched character is last or second to last match in input string. If true, return original match, else replace match with "^" character.
var str = `I want to replace \"this\" and \"that\" words, but NOT the one "here"`;
var res = str.replace(/(")/g, function(match, _, index) {
return index === str.lastIndexOf(match)
|| index === str.slice(0, str.lastIndexOf(match) -1)
.lastIndexOf(match)
? match
: "^"
});
console.log(res);
The problem with String.prototype.replace is that it only replaces the first occurrence without Regular Expression. To fix this, you need to add a g and the end of the RegEx, like so:
var mod = str => str.replace(/\\\"/g,'^');
mod('I want to replace \\"this\\" and \\"that\\" words, but NOT the one "here"');
A less effective but easier to understand to do what you wanted is to split the string with the delimiter and then join it with the replacement, like so:
var mod = str => str.split('\\"').join('^');
mod('I want to replace \\"this\\" and \\"that\\" words, but NOT the one "here"');
Note: You can wrap a string with either ' or ". Suppose your string contains ", i.e. a"a, you will need to put an \ in front of the " as "a"a" causes syntax error. 'a"a' won't cause syntax error as the parser knows the " is part of the string, but when you put a \ in front of " or any other special characters, it means the following character is a special character. So 'a\"a' === 'a"a' === "a\"a". If you want to store \, you will need to use \ regardless of the type of quote you use, so to store \", you will need to use '\\"', '\\\"' or "\\\"".

Last Character of regex match

I am trying to use a regex to detect a pattern in the current page query string.
For this reason I have the following regex:
var re = new RegExp("([?|&])" + key + "=.*?(&|#|$)", "i");
I am testing it against this input:
http://127.0.0.1:33822/?year=2015&country=Portugal&format=psd
And it works just fine finding the pattern.
What I am really trying to get is the last character index relative to the whole URL.
So for example if I want the index o the last 'd' character:
http://127.0.0.1:33822/?year=2015&country=Portugal&format=ps**d**
In this specific case I would want 60.
Thanks in advance
You can use match.index for that. It will give you where the match exists in the original string.
Then you can use the matche[0].length to find the last character in the match
key='format'
re = new RegExp("([?|&])" + key + "=.*?(&|#|$)", "i");
url='http://127.0.0.1:33822/?year=2015&country=Portugal&format=psd'
match=url.match(re)
console.log(match.index + match[0].length-1) // 60

Javascript RegExp help

I am trying to replace a certain text in Javascript.
newexp is a variable.
numexp is a variable
replacenamestring = new RegExp('Memberresumeexp\[1\]',"ig");
newexp = newexp.replace(replacenamestring,'Memberresumeexp[' + numexp + ']');
The above replace is not working.
How ever this works.
newexp = newexp.replace(/Memberresumeexp\[1\]/ig,'Memberresumeexp[' + numexp + ']');
Not able to figure out why?
Your first line creates a Javascript string, then parses the string as a regex.
Javascript string literals use \ as an escape character, so the \s are not part of the string value. Therefore, the [ and ] in your regex aren't escaped, so it's creating a character class.
You need to escape the \s by writing \\.
Here's a working example for you with one BIG caveat -- I changed "[1]" to "[\d+]" just in case you needed this for more cases of Memberresumeexp[<any number>]. Also, I hardcoded numexp, because I had not seen how it was initialized.
var replacenamestring = new RegExp('Memberresumeexp\\[\\d+\\]',"ig");
var newexp = "asdfasdflkj;lakwjef Memberresumeexp[1] asdfasdfasdf\nqwerqwerwer Memberresumeexp[2] qwerqwerwqerewr\n";
var numexp = 123;
if(replacenamestring.test(newexp))
{
newexp = newexp.replace(replacenamestring,'Memberresumeexp[' + numexp + ']');
}
It's a simple lexical syntax issue. In the first case, you're creating the RegExp object with the constructor, which starts from a string constant. Well, string constants have their own syntactic quirks, and in particular those backslashes in the string will be interpreted during its own parsing. By the time the RegExp constructor is called, those are gone.
The "native" RegExp syntax has its own quoting rules, which are such that the "[" and "]" portions of the pattern are correctly interpreted when you use that syntax.

Preserving case / capitalization with JavaScript replace method

I'm continuing work on a search term suggestion tool using Jquery UI. I am now working on displaying the results with the search term pattern in bold. I have implemented this functionality through patching the Autocomplete's _renderItem method. The problem I have now is that the replaced characters have the same case as those typed by the user in the input (e.g. if the user typed an "A" and the returned result was "America", the replaced text would be AmericA. Here's the code:
var exp = new RegExp(this.term, "gi") ;
var rep = item.label.replace( exp, "<span style='font-weight:bold;color:Black;'>"
+ this.term + "</span>");
As always, thanks in advance for any help.
You can use:
var rep = item.label.replace(exp,
"<span style='font-weight:bold;color:Black;'>$&</span>");
When replacing a string, $& means "the whole match", so you don't have to repeat the search term (in some cases you don't know it). In other flavors, you may use $0 or \0.
Also, remember to escape special characters in this.term.
You can add your expression in a group by encapsulating them in parentheses
var exp = new RegExp("(" + this.term + ")", "gi") ;
var rep = item.label.replace( exp, "<span style='font-weight:bold'>$1</span>");
You can the refere to that group using $1.
See here for more details about backreferences.

Using regex to search for keywords at the beginning of words only

I have a searching system that splits the keyword into chunks and searches for it in a string like this:
var regexp_school = new RegExp("(?=.*" + split_keywords[0] + ")(?=.*" + split_keywords[1] + ")(?=.*" + split_keywords[2] + ").*", "i");
I would like to modify this so that so that I would only search for it in the beginning of the words.
For example if the string is:
"Bbe be eb ebb beb"
And the keyword is: "be eb"
Then I want only these to hit "be ebb eb"
In other words I want to combine the above regexp with this one:
var regexp_school = new RegExp("^" + split_keywords[0], "i");
But I'm not sure how the syntax would look like.
I'm also using the split function to split the keywords, but I don't want to set a length since I don't know how many words there are in the keyword string.
split_keywords = school_keyword.split(" ", 3);
If I leave the 3 out, will it have dynamic length or just length of 1? I tried doing a
alert(split_keywords.lenght);
But didn't get a desired response
You should use the special word boundary character \b to match the beginning of a word. To create the expression for an arbitrary number of keywords, you can generate it in a loop.
var regex = '';
for(var i = split_keywords.length;i--; ) {
// two slashes are needed to insert `\` literally
regex += "(?=.*\\b" + split_keywords[i] + ")";
}
var regexp_school = new RegExp(regex, "i");
I'm not sure about performance, but you can also consider to use indexOf to test whether a substring is contained in a string.
Update:
If \b does not work for you (because of other "special" characters), and all your words are separated by a white space, you can use
"(?=.*\\s" + split_keywords[i] + ")"
or
"(?=.* " + split_keywords[i] + ")"
But for this to work you have to prepend the text you are searching in with a white space:
" " + textYouSearchIn
or you are write a more complex expression:
"(?=(^|.*\\s)" + split_keywords[i] + ")"
A couple points. First, you need to anchor the regex to the start of the string. Otherwise, if there is no match, there are a LOT of combinations that the regex engine must try before declaring a match failure (it must check all of them, in fact). Second, when splitting the string, use /\s+/ instead of a single space - this prevents getting empty matches in the resulting array in case there are multiple spaces between any keywords. Third, if there are empty strings in the array of keywords, you do not want to add them to the regex. Felix's solution is pretty close to the mark, but does not actually match the string once all the positive lookahead assertions are finished. That said, here's my proposed solution:
var split_keywords = school_keyword.split(/\s+/);
var regex = "^"; // Anchor to start of string.
for (var i = 0, len = split_keywords.length; i < len; ++i) {
if (split_keywords[i]) { // Skip empty keyword strings.
regex += "(?=.*?\\b" + split_keywords[i] + ")";
}
}
regex += ".*$"; // Add ending to actually match the line.
var regexp_school = new RegExp(regex, "i");
I've also changed the greedy quantifier to lazy. This is one case where it is applicable.

Categories

Resources