I have the following expression in JS (typescript, but I think everyone understands what it transpiles to):
markString(text: string) {
const regEx = new RegExp(this.partToHighlight, 'ig');
return text.replace(regEx, `<mark>${this.partToHighlight}<\/mark>`);
}
The problem is that this way, with the 'ig'-option, the matching value can have any case, upper or lower, but is always replaced by the partToHighlight-value. Instead the function should read the matched value, save it and output it surrounded with the HTML-tags. How do I do this? I am pretty sure this is a duplicate question, but I couldn't find the one asked before.
You need to replace with the found match, $&:
markString(text: string) {
const regEx = new RegExp(this.partToHighlight, 'ig');
return text.replace(regEx, "<mark>$&</mark>");
}
Using $&, you replace with found match with the the same text found and do not need to hardcode the replacement, nor use any callbacks.
See "Specifying a string as a parameter" for more details.
As mentionned in comments you will need to use RegExp.lastMatch or $&, to point out to the matched substring, in your replace() method:
const regEx = new RegExp(this.partToHighlight, 'ig');
return text.replace(regEx, `<mark>$&<\/mark>`);
Related
I have a regular expression like this and it works fine using https://regexr.com/
([a-zA-Z0-9-.~%!$&'()*+,;=#]+(/[a-zA-Z0-9-.~%!$&'()+,;=:#]+)/?|(/[a-zA-Z0-9-.~%!$&'()*+,;=:#]+)+/?)(?[a-zA-Z0-9-.~%!$&'()+,;=:#/?])?(#[a-zA-Z0-9-._~%!$&'()+,;=:#/?])?
I would like to use it with RegExp() like below(I just put the above string inside the raw string), but it does not work. Do I need to do any other treatment?
const pattern =String.raw`([a-zA-Z0-9\-._~%!$&'()*+,;=#]+(\/[a-zA-Z0-9\-._~%!$&'()*+,;=:#]+)*\/?|(\/[a-zA-Z0-9\-._~%!$&'()*+,;=:#]+)+\/?)(\?[a-zA-Z0-9\-._~%!$&'()*+,;=:#/?]*)?(\#[a-zA-Z0-9\-._~%!$&'()*+,;=:#/?]*)?`;
let re = new RegExp(pattern);
return re.test(somestring)
I also tried enclose the regex with / and / like below and it does not work either. It allows spaces but I don't really allow space.
const re = new RegExp(/([a-zA-Z0-9\-._~%!$&'()*+,;=#]+(\/[a-zA-Z0-9\-._~%!$&'()*+,;=:#]+)*\/?|(\/[a-zA-Z0-9\-._~%!$&'()*+,;=:#]+)+\/?)(\?[a-zA-Z0-9\-._~%!$&'()*+,;=:#/?]*)?(\#[a-zA-Z0-9\-._~%!$&'()*+,;=:#/?]*)?/);
Updates:
I guess my question should be how do I make sure it matches full text like what I can do test in the website above(attached screenshot below)
I think the root of this question is that regexr is matching on the full string rather than just a part. .test() will return true if part of the regex matches. if you want to only return true when matching the on the full string I would suggest using start ^ and end $ delimiters.
const pattern =String.raw`^([a-zA-Z0-9\-._~%!$&'()*+,;=#]+(\/[a-zA-Z0-9\-._~%!$&'()*+,;=:#]+)*\/?|(\/[a-zA-Z0-9\-._~%!$&'()*+,;=:#]+)+\/?)(\?[a-zA-Z0-9\-._~%!$&'()*+,;=:#/?]*)?(\#[a-zA-Z0-9\-._~%!$&'()*+,;=:#/?]*)?$`;
let re = new RegExp(pattern);
console.log(re.test('asdf```'))
Match the beginning ^ and end $ of a string to get an exact match, otherwise a substring will be accepted.
const re = new RegExp('^regex$')
On the sample string:
const reStr = `^([a-zA-Z0-9\-._~%!$&'()*+,;=#]+(\/[a-zA-Z0-9\-._~%!$&'()*+,;=:#]+)*\/?|(\/[a-zA-Z0-9\-._~%!$&'()*+,;=:#]+)+\/?)(\?[a-zA-Z0-9\-._~%!$&'()*+,;=:#/?]*)?(\#[a-zA-Z0-9\-._~%!$&'()*+,;=:#/?]*)?$`
I have a little code snippet where I use Regular Expressions to rip off punctuation, numbers etc from a string. I am getting undefined along with output of my ripped string. Can someone explain whats happening? Thanks
var regex = /[^a-zA-z\s\.]|_/gi;
function ripPunct(str) {
if ( str.match(regex) ) {
str = str.replace(regex).replace(/\s+/g, "");
}
return str;
}
console.log(ripPunct("*#£#__-=-=_+_devide-00000110490and586#multiply.edu"));
You should pass a replacement pattern to the first replace method, and also use A-Z, not A-z, in the pattern. Also, there is no point to check for a match before replacing, just use replace directly. Also, it seems the second chained replace is redundant as the first one already removes whitespace (it contains \s). Besides, the |_ alternative is also redundant since the [^a-zA-Z\s.] already matches an underscore as it is not part of the symbols specified by this character class.
var regex = /[^a-zA-Z\s.]/gi;
function ripPunct(str) {
return str.replace(regex, "");
}
console.log(ripPunct("*#£#__-=-=_+_devide-00000110490and586#multiply.edu"));
I am currently looking for a way to turn matching text into a bold html line. I have it partially working except for special characters giving me problems because I desire to maintain the original string, but not compare the original string.
Example:
Given the original string:
Taco John's is my favorite place to eat.
And wanting to match:
is my 'favorite'
To get the desired result:
Taco John's <b>is my favorite</b> place to eat.
The way I'm currently getting around the extra quotes in the matching string is by replacing them
let regex = new RegExp('('+escapeRegexCharacters(matching_text.replace(/[^a-z 0-9]/gi,''))+')',"gi")
let html= full_text.replace(/[^a-z 0-9]/gi,'').replace(regex, "<b>$1</b>")}}></span>
This almost works, except that I lose all punctuation:
Taco Johns <b>is my favorite</b> place to eat
Is there any way to use regex, or another method, to add tags surrounding a matching phrase while ignoring both case and special characters during the matching process?
UPDATE #1:
It seems that I am being unclear. I need the original string's puncuation to remain in the end result's html. And I need the matching text logic to ignore all special characters and capitalization. So is my favorite is My favorite and is my 'favorite' should all trigger a match.
Instead of removing the special characters from the string being searched, you could inject in your regular expression a pattern between each character-to-match that will skip any special characters that might occur. That way you build a regular expression that can be applied directly to the string being searched, and the replacing operation will thus not touch the special characters outside of the matches:
let escapeRegexCharacters =
s => s.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&"),
full_text = "Taco John's is My favorite place to eat.";
matching_text = "is my 'favorite'";
regex = new RegExp(matching_text.replace(/[^a-z\s\d]/gi, '')
.split().map(escapeRegexCharacters).join('[^a-z\s\d]*'), "gi"),
html = full_text.replace(regex, "<b>$&</b>");
console.log(html);
Regexps are useful where there is a pattern, but, in this case you have a direct match, so, the good approach is using a String.prototype.replace:
function wrap(source, part, tagName) {
return source
.replace(part,
`<${tagName}>${part}</${tagName}>`
)
;
}
At least, if there is a pattern, you should edit your question and provide it.
As an option, for single occurrence case - use String.split
Example replacing '###' with '###' :
let inputString = '1234###5678'
const chunks = inputString.split('###')
inputString = `${chunks[0]}###${chunks[1]}`
It's possible to avoid using a capture group with the $& replacement string, which means "entire matched substring":
var phrase = "Taco John's is my favorite place to eat."
var matchingText = "is my favorite"
var re = new RegExp(escapeRegexCharacters(matchingText), "ig");
phrase.replace(re, "<b>$&</b>");
(Code based on obarakon's answer.)
Generalizing, the regex you could use is my /w+. You can use that in a replacer function so that you can javascript manipulate the resultant text:
var str = "Taco John's is my favorite place to eat.";
var html = str.replace(/is my \w*/, function (x) {
return "<b>" + x + "</b>";
} );
console.log(html);
I am having issues matching a string using regex in javascript. I am trying to get everything up to the word "at". I am using the following and while it doesn't return any errors, it also doesn't do anything either.
var str = "Team A at Team B";
var matches = str.match(/(.*?)(?=at|$)/);
I tried multiple regex patterns before coming across this SO post, Regex to capture everything before first optional string, but it doesn't to return what I want.
Remove the ? at your first capturing group, and |$ from your second, and add ^ to mark beginning of string:
str.match(/^(.*)(?=at)/)
Alternatively (I personally find below easier to read, but your call):
str.substr(0, str.search(/\bat\b/))
Say I wanted to make the following re-usable:
function replace_foo(target, replacement) {
return target.replace("string_to_replace",replacement);
}
I might do something like this:
function replace_foo(target, string_to_replace, replacement) {
return target.replace(string_to_replace,replacement);
}
With string literals this is easy enough. But what if I want to get a little more tricky with the regex? For example, say I want to replace everything but string_to_replace. Instinctually I would try to extend the above by doing something like:
function replace_foo(target, string_to_replace, replacement) {
return target.replace(/^string_to_replace/,replacement);
}
This doesn't seem to work. My guess is that it thinks string_to_replace is a string literal, rather than a variable representing a string. Is it possible to create JavaScript regexes on the fly using string variables? Something like this would be great if at all possible:
function replace_foo(target, string_to_replace, replacement) {
var regex = "/^" + string_to_replace + "/";
return target.replace(regex,replacement);
}
There's new RegExp(string, flags) where flags are g or i. So
'GODzilla'.replace( new RegExp('god', 'i'), '' )
evaluates to
zilla
With string literals this is easy enough.
Not really! The example only replaces the first occurrence of string_to_replace. More commonly you want to replace all occurrences, in which case, you have to convert the string into a global (/.../g) RegExp. You can do this from a string using the new RegExp constructor:
new RegExp(string_to_replace, 'g')
The problem with this is that any regex-special characters in the string literal will behave in their special ways instead of being normal characters. You would have to backslash-escape them to fix that. Unfortunately, there's not a built-in function to do this for you, so here's one you can use:
function escapeRegExp(s) {
return s.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')
}
Note also that when you use a RegExp in replace(), the replacement string now has a special character too, $. This must also be escaped if you want to have a literal $ in your replacement text!
function escapeSubstitute(s) {
return s.replace(/\$/g, '$$$$');
}
(Four $s because that is itself a replacement string—argh!)
Now you can implement global string replacement with RegExp:
function replace_foo(target, string_to_replace, replacement) {
var relit= escapeRegExp(string_to_replace);
var sub= escapeSubstitute(replacement);
var re= new RegExp(relit, 'g');
return target.replace(re, sub);
}
What a pain. Luckily if all you want to do is a straight string replace with no additional parts of regex, there is a quicker way:
s.split(string_to_replace).join(replacement)
...and that's all. This is a commonly-understood idiom.
say I want to replace everything but string_to_replace
What does that mean, you want to replace all stretches of text not taking part in a match against the string? A replacement with ^ certainly doesn't this, because ^ means a start-of-string token, not a negation. ^ is only a negation in [] character groups. There are also negative lookaheads (?!...), but there are problems with that in JScript so you should generally avoid it.
You might try matching ‘everything up to’ the string, and using a function to discard any empty stretch between matching strings:
var re= new RegExp('(.*)($|'+escapeRegExp(string_to_find)+')')
return target.replace(re, function(match) {
return match[1]===''? match[2] : replacement+match[2];
});
Here, again, a split might be simpler:
var parts= target.split(string_to_match);
for (var i= parts.length; i-->0;)
if (parts[i]!=='')
parts[i]= replacement;
return parts.join(string_to_match);
As the others have said, use new RegExp(pattern, flags) to do this. It is worth noting that you will be passing string literals into this constructor, so every backslash will have to be escaped. If, for instance you wanted your regex to match a backslash, you would need to say new RegExp('\\\\'), whereas the regex literal would only need to be /\\/. Depending on how you intend to use this, you should be wary of passing user input to such a function without adequate preprocessing (escaping special characters, etc.) Without this, your users may get some very unexpected results.
Yes you can.
https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions
function replace_foo(target, string_to_replace, replacement) {
var regex = new RegExp("^" + string_to_replace);
return target.replace(regex, replacement);
}
A really simple solution to this is this:
function replace(target, string_to_replace, replacement) {
return target.split(string_to_replace).join(replacement);
}
No need for Regexes at all
It also seems to be the fastest on modern browsers https://jsperf.com/replace-vs-split-join-vs-replaceall
I think I have very good example for highlight text in string (it finds not looking at register but highlighted using register)
function getHighlightedText(basicString, filterString) {
if ((basicString === "") || (basicString === null) || (filterString === "") || (filterString === null)) return basicString;
return basicString.replace(new RegExp(filterString.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\\\$&'), 'gi'),
function(match)
{return "<mark>"+match+"</mark>"});
}
http://jsfiddle.net/cdbzL/1258/