Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I place newlines in my regex to make it more readable? [duplicate]

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?

like image 317
temporary_user_name Avatar asked Sep 14 '25 11:09

temporary_user_name


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)

like image 128
CertainPerformance Avatar answered Sep 16 '25 01:09

CertainPerformance