9

How can I:

  1. Convert a JavaScript RegExp with flags to a String literal (think JSON),
  2. And convert that literal back to a regex?

For example with the String "the weather is nice today":

var myRe = new RegExp("weather","gi");
var myReToString = myRe.toString(); // myReToString is now "/weather/gi"

var myReCopy = /* How to get this copy only from myReToString ? */

To modify the original RegExp properties see torazaburo's answer.

Community
  • 1
  • 1
user2305193
  • 2,079
  • 18
  • 39
  • 7
    My I ask what is the use case for converting regex to string and back again? – swlim Jul 02 '16 at 13:37
  • 3
    Your `.replace()` method would break any regex that contained a forward slash in the actual expression. Also, your technique assumes the `gi` flags should always be used. – nnnnnn Jul 02 '16 at 13:48
  • 2
    `eval` would do it. – Bergi Jul 02 '16 at 14:03
  • Related: [Serialization of RegExp](http://stackoverflow.com/questions/12075927/serialization-of-regexp), [Can I store RegExp and Function in JSON?](http://stackoverflow.com/questions/8328119/can-i-store-regexp-and-function-in-json) – GingerPlusPlus Jul 02 '16 at 14:46
  • @SWLim: I wanted to 'extend'/add to the regex, to something like this: "weather | is " – user2305193 Jul 02 '16 at 17:48
  • @kyll: go ahead, I can only learn, you can delete our two comments if you can too – user2305193 Jul 02 '16 at 17:49
  • @nnnnnn yes, the gi flags are just an example – user2305193 Jul 02 '16 at 17:51
  • 1
    Done. Let me know what you think. Also, feel free to [edit] your post some more or rollback my changes if you don't like them. – Kyll Jul 03 '16 at 12:39

3 Answers3

7

Take a look at the accessor properties on the RegExp prototype such as source and flags. So you can do:

var myRe = new RegExp("weather", "gi")

var copyRe = new RegExp(myRe.source, myRe.flags); 

For the spec see http://www.ecma-international.org/ecma-262/6.0/#sec-get-regexp.prototype.flags.

Serializing and deserializing regexps

If your intent in doing this is to serialize the regexp, such as into JSON, and then deserialize it back, I would recommend storing the regexp as a tuple of [source, flags], and then reconstituting it using new RexExp(source, flags). That seems slightly cleaner than trying to pick it apart using regexp or eval'ing it. For instance, you could stringify it as

function stringifyWithRegexp(o) {
  return JSON.stringify(o, function replacer(key, value) {
    if (value instanceof RegExp) return [value.source, value.flags];
    return value;
  });
}

On the way back you can use JSON.parse with a reviver to get back the regexp.

Modifying regexps

If you want to modify a regexp while retaining the flags, you can create a new regexp with modified source and the same flags:

var re = /weather/gim;
var newre = new RegExp(re.source + "| is", re.flags);
  • 3
    The whole point is that you don't have access to the original regex. – 4castle Jul 02 '16 at 13:57
  • 2
    *"and back again?"* means from a string. The output of step 1 is the input of step 2. – 4castle Jul 02 '16 at 13:59
  • 4
    hence the question to OP of why he/she needs to do this. Perhaps there's something better that can solve the root problem :) – swlim Jul 02 '16 at 14:01
  • Actually you answer what I meant to ask, thanks @SWLim for asking to clarify. Because the direct answer to the question is eval, I accepted it for the answer, however yours did actually solve my problem, this mentioned your answer in the edit – user2305193 Jul 02 '16 at 20:12
  • 3
    No problem. Just a word of caution, I'd avoid eval (Google 'javascript evil eval' and you'll see many articles on it), but it should be fine as long as [you know what you're dealing with](http://stackoverflow.com/questions/197769/when-is-javascripts-eval-not-evil). – swlim Jul 02 '16 at 20:36
3

You can use eval to get back the regular expression:

var myRe = RegExp("weather", "gi");
var myReString = myRe.toString();
eval(myReString); // => /weather/gi

NOTE: eval can execute arbitrary javascript expression. Use eval only if you're sure the string is generated from regular expression toString method.

falsetru
  • 357,413
  • 63
  • 732
  • 636
3

I'm not sure if this code works in all cases, but I'm sure that this can be done using regex:

var regex = new RegExp('^/(.+)/(.*)$')
function stringToRegex(s) {
    var match = s.match(regex)
    return new RegExp(match[1], match[2])
}

var test = new RegExp("weather", "gi")

console.log(stringToRegex(test.toString()))
console.log(stringToRegex(test.toString()).toString() === test.toString())

Regular expression visualization

Debuggex Demo

GingerPlusPlus
  • 5,336
  • 1
  • 29
  • 52
  • 1
    I'm pretty sure this will work in all cases, because the `.+` is greedy. The second `/` will only match the last one in the string. – 4castle Jul 02 '16 at 15:16