crowhill
crowhill

Reputation: 2558

How to preserve \ when converting a string to a RegEx

I have some regex that are coming to me via JSON object, like so:

{
  config: { 
    regEx: "/^$/"
  }
}

I am trying to convert the above string into a regex, like so:

const re = new RegExp(config.regEx);

This works, but RegExp is ~helpfully~ escaping the / characters and returning //^$// (not /^$/)

How can I best turn the string into a regex without escaping the /?

EDIT: I have no control over the original string returned. It is what it is.

Upvotes: 0

Views: 187

Answers (3)

IronFlare
IronFlare

Reputation: 2322

Escaping is not exactly the word for what's going on here.

When composing a RegEx with an inline definition, it's normally impossible (without a backslash) to include a forward slash at the start of the expression, since the double slash would be interpreted as a comment.

let re = //abc/g;

This is where new RegExp() comes into play. You can feed the function a string and it will encapsulate the contents into a RegEx -- without evaluating the contents.

So really, what you're seeing in the console is not escaping, but rather two different types of slashes in succession:

  1. The outer slashes that denote the RegEx, then
  2. The inner slashes that are part of your encapsulated string.

Short of using eval(), there's no way to use a string to define a regular expression in such a way that the slashes are interpreted as its "bounds". Please don't use eval().

The simplest way to get your intended behavior is to just strip off the first and last characters of the string you're passing in like so:

const re = new RegExp(config.regEx.slice(1,-1));

If you want to trim off the slashes conditionally, you could (ironically) use a regular expression:

const TRIM_SLASH = new RegExp('^/(.*)/$');
let stripped = config.regEx.replace(TRIM_SLASH,'$1');
const re = new RegExp(stripped);

Upvotes: 1

Casimir et Hippolyte
Casimir et Hippolyte

Reputation: 89557

The way the pattern is stored doesn't seem to be designed for javascript, so you have to extract the eventual global modifiers and to remove the delimiters:

let toto = {
  config: { 
    regEx: "/^$/"
  }
};

let delimiter = toto.config.regEx[0];
let arr = toto.config.regEx.split(delimiter);

arr.shift();

let modifiers = arr.pop();
let pattern = arr.join(delimiter);

/* eventually, you need to escape backslashes (depending of how patterns
   are written, if it isn't the case already):
pattern = pattern.replace(/\\/g, '\\\\'); */

const re = new RegExp(pattern, modifiers);

Upvotes: 0

MilesZew
MilesZew

Reputation: 687

Simply remove the /'s around you regex, like so : "/^$/" becomes "^$".

The /'s around your regex when not using regexp constructor are simply the way to tell javascript (v8) that it's a regex, the same way "'s tell javascript that it's a string. (I can see why this might confuse you due to the fact that /^$/.toString() results in "/^$/")

To remove the /'s from the string do this:

config.regEx.replace(/(^\/)|(\/$)/g, '')

Upvotes: 1

Related Questions