0

I have a very simple regex that I am using for highlighting search terms in my application. If a user types in 'stack' into the search form, for example, the following regular expression is used as a string argument for preg_match_all to highlight the results:

"/\b((stack|stacks))\b/i"

I am using json_encode to output some of my configuration options for my application, including the regex above. I need this regex on the client-side because I am lazy-loading pagination items in an infinite-scroll fashion, and I want to take advantage of the client-side to parse the HTML for the proper search term highlighting.

My JS configuration object now appears similar to:

config = {
   searchRegex: "/\b((stack|stacks))\b/i",
   // ... more options
}

If searchRegex wasn't a string, I wouldn't have a problem. It would automatically be a regular expression object, and there is nothing in that regex that JavaScript doesn't support. But now, I have to resort to parsing the string to get the appropriate arguments for the RegExp constructor, which involves removing the delimiters and getting the modifier(s). With all the escaped characters that could be present, this doesn't seem like a viable or sane option.

How would I convert searchRegex to become a regular expression object?

danronmoon
  • 3,814
  • 5
  • 34
  • 56
  • See http://stackoverflow.com/questions/874709/converting-user-input-string-to-regular-expression. It does not give another solution than using the RegExp constructor, but I think there isn't. – Lorenz Meyer Oct 07 '13 at 20:12
  • Why not simplifying your reg-ex with `/\b(stacks?)\b/i`, which would then be mutated into `/\\b(stacks?)\\b/i` ? – Stphane Oct 08 '13 at 08:55

4 Answers4

1

A really hacky way to do this is to eval it. If you can trust the inputs, it might be an okay solution.

function evalRegExp(str) {
  return eval(str);
}

var re = evalRegExp("/foo/i");
// => /foo/i

If you use this a lot, it might be okay to add this as a method directly to RegExp

RegExp.eval = function(str) {
  return eval(str);
};

var re = RegExp.eval("/foo/i");
// => /foo/i
maček
  • 76,434
  • 37
  • 167
  • 198
  • shouldnt we use RegExp.prototype.evalRegExp = function() {} ; – Psych Half Oct 07 '13 at 20:43
  • @PsychHalf hmm no. If the function is put on the prototype, it means we need an instance of RegExp in order to call that function. Putting the function directly on `RegExp` makes it sort of like a factory that actually returns a new instance of `RegExp`. – maček Oct 07 '13 at 21:56
  • Never thought of this, thanks. I tend to refrain from `eval` (and rightfully so) but I forgot that it would be that simple if I did use it. – danronmoon Oct 07 '13 at 22:25
  • @danronmoon, right, `eval` is generally an ill-advised thing to use, but in this particular case, if you trust the inputs, it's probably fine. – maček Oct 07 '13 at 22:58
  • @maček you are right.. the code runs fine but in my debugger i got.. Line 1: RegExp.eval = function(str) { --- Expected an identifier and instead saw 'eval' (a reserved word). Line 1: RegExp.eval = function(str) { --- eval is evil. Line 2: return eval(str); --- eval is evil. so i was just asking.. – Psych Half Oct 08 '13 at 02:27
0

Maybe not the best parse but i've got it working parsed as an array [regexp, modifiers] ready to create a new instance of RegExp. Hope it helps...

'/some[a-z]+regex/i'.replace(/^(.)(.+)\1([gim])+/, function (foo, bar, regexp, modifiers) { return [regexp, modifiers].join('___') }).split('___')

Andrés Torres
  • 747
  • 5
  • 16
  • I think you'd have trouble with escaped delimiters here. Such as `/foo\/bar/i`. Not to mention, if the input string had `___` in it, it would also fail. – maček Oct 07 '13 at 20:39
  • @maček yeah, you're right :( I regret about the entire "solution" right now... just nevermind. – Andrés Torres Oct 07 '13 at 20:47
0

Thanks for your answers. I decided to output the regex-based string sans modifiers and delimiters to the client and use JS to pass it and the separated modifier to the RegExp constructor. Ended up with something similar to:

config = {
    searchRegex: '\b((stack|stacks))\b',
    modifiers: 'i'
}

// ... later
model.initialize = function () {
    config.searchRegex = new RegExp(config.searchRegex, config.modifiers || '');
};
danronmoon
  • 3,814
  • 5
  • 34
  • 56
-5

Use unescape()

http://www.w3schools.com/jsref/jsref_unescape.asp

var str="Need tips? Visit W3Schools!";
var str_esc=escape(str);
document.write(str_esc + "<br>")
document.write(unescape(str_esc))
Populus
  • 7,470
  • 3
  • 38
  • 54