I have a really long email-matching regex in JavasScript that I would like to break into multiple lines without changing the regex functionality. I know some regex engines offer a way to insert newlines for readability, is there a way to do that in JS?
-
Can you provide the regex? – ibrahim mahrir Nov 22 '18 at 00:01
-
1I mean I could but it shouldn't make any difference to the question, it's arbitrary. It applies equally to all regexes. But it's the email-matching regex [from the MDN docs](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#Validation). And yeah that's true I could do it that way, but it's not really exactly what I'm looking for here and more of a work-around. – temporary_user_name Nov 22 '18 at 00:06
1 Answers
There's no built-in way to accomplish such a thing, but it's not hard to accomplish it yourself. You can use a template literal with String.raw
, which will allow you to use newlines in the regex string, without having to double-escape backslashes, and then you can replace all newlines with the empty string before passing it to new RegExp
:
const patternStr = String.raw`^
[fg]oo
=
\war`;
const pattern = new RegExp(patternStr.replace(/\n/g, ''));
console.log(pattern.test('foo=bar'));
console.log(pattern.test('goo=bar'));
console.log(pattern.test('hoo=bar'));
You can use a similar technique to allow comments as well:
const patternStr = String.raw`
^ // Match the beginning of the string
[fg]oo // Match either f or g, followed by oo
= // Match an equals sign
\war // Match a word character, followed by "ar"
`;
const pattern = new RegExp(
patternStr.replace(/(?: *\/\/.*)?\n/g, '')
);
console.log(pattern.test('foo=bar'));
console.log(pattern.test('goo=bar'));
console.log(pattern.test('hoo=bar'));
The (?: *\/\/.*)?\n
pattern means:
(?: *\/\/.*)?
- An optional group of zero or more spaces, followed by //
, followed by non-newline characters
\n
- followed by a newline
Of course, this means it'll be impossible to write //
as is in the regex, but that's OK, you can just escape forward slashes just like you do with regular expression literals (it'll be parsed by the RegExp constructor as an unnecessary escape character):
const patternStr = String.raw`
^ // Match the beginning of the string
\/\/ // Match two literal forward slashes
`;
const pattern = new RegExp(
patternStr.replace(/(?: *\/\/.*)?\n/g, '')
);
console.log(pattern.test('//foo'));
console.log(pattern.test('foo'));
Another way would be to allow literal //
s in the template literal by, when matching the comment // <text> \n
, make sure that <text>
doesn't have any //
s in it. This would mean that only the final //
on a line would be parsed as a comment, allowing you to use //
s earlier on the line, without escaping, without problems, by using (?:(?!\/\/).)*
instead of .*
:
const patternStr = String.raw`
^ // Match the beginning of the string
// // Match two literal forward slashes
`;
const pattern = new RegExp(
patternStr.replace(/(?: *\/\/(?:(?!\/\/).)*)?\n/g, '')
);
console.log(pattern.test('//foo'));
console.log(pattern.test('foo'));
Of course, this will mean that //
s will only be parsed as actual double-forward-slashes in the regex if there's another //
farther right in the line. (If there isn't another //
later, you'll have to use \/\/
instead)

- 356,069
- 52
- 309
- 320