Create RegExps on the fly using string variables

JavascriptRegex

Javascript Problem Overview


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);
}

Javascript Solutions


Solution 1 - Javascript

There's new RegExp(string, flags) where flags are g or i. So

'GODzilla'.replace( new RegExp('god', 'i'), '' )

evaluates to

zilla

Solution 2 - Javascript

> 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);

Solution 3 - Javascript

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.

Solution 4 - Javascript

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);
}

Solution 5 - Javascript

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

Solution 6 - Javascript

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/

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbuleyView Question on Stackoverflow
Solution 1 - Javascriptmeder omuralievView Answer on Stackoverflow
Solution 2 - JavascriptbobinceView Answer on Stackoverflow
Solution 3 - JavascriptKentView Answer on Stackoverflow
Solution 4 - JavascriptKristof NeirynckView Answer on Stackoverflow
Solution 5 - JavascriptJack AllanView Answer on Stackoverflow
Solution 6 - JavascriptZhurov KonstantinView Answer on Stackoverflow