-1

I want to make an input where users can write a custom regex in literal notation. I then want to create a RegExp out of that literal notation string.

Something like this:

const literalNotationStr = `/literal/i`;
const regex = makeRegexFromLiteralNotationString(literalNotationStr)

function makeRegexFromLiteralNotationString(str: string): RegExp {
  // ... magic code ...
}

Is there a function I'm missing here or is this the kind of thing where you have to parse and build yourself?

Seph Reed
  • 8,797
  • 11
  • 60
  • 125
  • 1
    Since it's from an input, do they really need to provide the `/` delimiters? Other sites that do this put the delimiters outside the input to show that they're not needed. The flags could go in a separate input. –  Oct 28 '20 at 01:13
  • ...or the way [regex101](https://regex101.com/) does it is pretty nice. –  Oct 28 '20 at 01:17
  • 1
    You say `literal notation` string but what does that mean ? If you have an input box, everything that is _typed_ in that box goes into a variable unchanged. That variable is passed to the RegExp function unchanged. I guess I don't understand. –  Oct 28 '20 at 01:17
  • @Maxt8r: They mean the content of the string contains regex literal notation. –  Oct 28 '20 at 01:19
  • If on the otherhand, you are trying to parse delimiters for some reason, you make the same mistake as regex101.com does, it's an added user burdon that should not be . –  Oct 28 '20 at 01:19
  • @slappy can you give an example of regex literal notation ? Cause I don't know that. –  Oct 28 '20 at 01:21
  • `/foo/gi`. The literal is delimited by the forward slashes, with the trailing flags optional. –  Oct 28 '20 at 01:21
  • @slappy but as I said, those are delimiters that have nothing to do with regex syntax. –  Oct 28 '20 at 01:22
  • If you are trying to discern the _flag options_ use another input box, otherwise the problem of delimiters will take you down.. –  Oct 28 '20 at 01:23
  • @Maxt8r: They have to do with the literal syntax, but not the regex grammar. –  Oct 28 '20 at 01:23
  • @slappy as I said literal syntax is not related to regex. It's too complex to discern delimiters within a regex context, stay away from that, trust me. –  Oct 28 '20 at 01:24
  • @Maxt8r: Literal syntax in a language exists to create instances of certain types without the aid of things like constructors. JavaScript includes regular expression literals, which are delimited by the forward slashes. –  Oct 28 '20 at 01:26
  • Then use a JS parser, don't do it yourself. Is it that simple you could do it ? Where do delimiters start and end when quote like operators and regex ? –  Oct 28 '20 at 01:28
  • @Maxt8r: They could parse away just the literal delimiters very easily, and then use the `RegExp` constructor. Using `const re = new Function("return " + literalNotationStr)()` would use the built-in JS parser, but I'd think that it *may* be more computationally expensive, but I'm not sure. –  Oct 28 '20 at 01:31
  • ...and there's no guarantee that the user would have limited their input to regex syntax. –  Oct 28 '20 at 01:31
  • I claim that regex syntax conceals delimiters like no other language. Do what you think, but I think JS `/../` notation itself uses very rudimentary rules to avoid regex constructs. Might as well find the firs and last `/` and hope for the best. –  Oct 28 '20 at 01:32
  • @Maxt8r: That's the point. Those are the regex literal delimiters. Just need to account for the optional flags at the end. –  Oct 28 '20 at 01:38

2 Answers2

0

You'll have to

(1) grab the flags

(2) slice off the slash delimiters from the beginning and end of the pattern

const literalNotationStr = `/literal/i`;
const regex = makeRegexFromLiteralNotationString(literalNotationStr)
console.log(regex.test('LITERAL'));

function makeRegexFromLiteralNotationString(str){
  const [, patternContent, flags] = str.match(/^\/(.+)\/(\w*)$/);
  return new RegExp(patternContent, flags);
}

But you'll have to make sure the input string has its backslashes properly escaped, eg:

const literalNotationStr = String.raw`/foo\w+/i`;

and not

const literalNotationStr = `/foo\w+/i`;
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
-1

The flag has to be provided as the second argument. You can e.g. split the literal to get the Regex body and the flag separately and then use it within the Regex constructor.

const literalNotationStr = '/literal/i';

const createRegex = (str) => {
   const [, literal, flag] = str.split('/');
   return new RegExp(literal, flag);
};

console.log(createRegex(literalNotationStr));
kind user
  • 40,029
  • 7
  • 67
  • 77
  • 2
    You can't reliably use `split` for this, since the character you're splitting on can be used within the regex itself. –  Oct 28 '20 at 01:12