Как разбить длинное регулярное выражение на несколько строк в JavaScript?


У меня есть очень длинное регулярное выражение, которое я хочу разделить на несколько строк в своем коде JavaScript, чтобы сохранить длину каждой строки 80 символов в соответствии с правилами JSLint. Это просто лучше для чтения, я думаю. Вот образец шаблона:

var pattern = /^(([^<>()[].,;:s@"]+(.[^<>()[].,;:s@"]+)*)|(".+"))@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}])|(([a-zA-Z-0-9]+.)+[a-zA-Z]{2,}))$/;
6 103

6 ответов:

вы можете преобразовать его в строку и создать выражение, вызвав new RegExp():

var myRE = new RegExp (['^(([^<>()[\]\.,;:\s@\"]+(\.[^<>(),[\]\.,;:\s@\"]+)*)',
                        '|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.',
                        '[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+',
                        '[a-zA-Z]{2,}))$'].join(''));

Примечания:

  1. при преобразовании выражение литерал в строку вам нужно избежать всех обратных косых черт, поскольку обратные косые черты используются при оценке строковый литерал. (См. комментарий Кайо для более подробной информации.)
  2. RegExp принимает модификаторы в качестве второго параметра

    /regex/g => new RegExp('regex', 'g')

[ Дополнение ES20xx (тегами шаблона)]

в ES20xx вы можете использовать помеченные шаблоны. Смотрите фрагмент.

Примечание:

  • недостатком здесь является то, что вы не можете использовать простые пробелы в строке регулярного выражения (всегда используйте \s,\s+,\s{1,x},\t,\n etc).

(() => {
  const createRegExp = (str, opts) => 
    new RegExp(str.raw[0].replace(/\s/gm, ""), opts || "");
  const yourRE = createRegExp`
    ^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|
    (\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|
    (([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$`;
  console.log(yourRE);
  const anotherLongRE = createRegExp`
    (\byyyy\b)|(\bm\b)|(\bd\b)|(\bh\b)|(\bmi\b)|(\bs\b)|(\bms\b)|
    (\bwd\b)|(\bmm\b)|(\bdd\b)|(\bhh\b)|(\bMI\b)|(\bS\b)|(\bMS\b)|
    (\bM\b)|(\bMM\b)|(\bdow\b)|(\bDOW\b)
    ${"gi"}`;
  console.log(anotherLongRE);
})();

расширяя @ KooiInc ответ, вы можете избежать ручного экранирования каждого специального символа с помощью source свойства RegExp "объект".

пример:

var urlRegex= new RegExp(''
  + /(?:(?:(https?|ftp):)?\/\/)/.source     // protocol
  + /(?:([^:\n\r]+):([^@\n\r]+)@)?/.source  // user:pass
  + /(?:(?:www\.)?([^\/\n\r]+))/.source     // domain
  + /(\/[^?\n\r]+)?/.source                 // request
  + /(\?[^#\n\r]*)?/.source                 // query
  + /(#?[^\n\r]*)?/.source                  // anchor
);

или если вы хотите избежать повторения .source собственность вы можете сделать это с помощью Array.map() функция:

var urlRegex= new RegExp([
  /(?:(?:(https?|ftp):)?\/\/)/      // protocol
  ,/(?:([^:\n\r]+):([^@\n\r]+)@)?/  // user:pass
  ,/(?:(?:www\.)?([^\/\n\r]+))/     // domain
  ,/(\/[^?\n\r]+)?/                 // request
  ,/(\?[^#\n\r]*)?/                 // query
  ,/(#?[^\n\r]*)?/                  // anchor
].map(function(r) {return r.source}).join(''));

в ES6 функция карты может быть уменьшена до: .map(r => r.source)

через строки new RegExp неудобно, потому что вы должны избежать всех обратных косых черт. Вы можете написать меньшие регулярные выражения и объединить их.

давайте разделим это регулярное выражение

/^foo(.*)\bar$/

мы будем использовать функцию, чтобы сделать вещи более красивыми позднее

function multilineRegExp(regs, options) {
    return new RegExp(regs.map(
        function(reg){ return reg.source; }
    ).join(''), options);
}

а теперь давайте рок

var r = multilineRegExp([
     /^foo/,  // we can add comments too
     /(.*)/,
     /\bar$/
]);

поскольку он имеет стоимость, попробуйте построить реальное регулярное выражение только один раз, а затем использовать его.

в регулярном выражении выше отсутствуют некоторые черные косые черты, которые не работают должным образом. Итак, я отредактировал регулярное выражение. Пожалуйста, учитывайте это регулярное выражение, которое работает 99.99% для проверки электронной почты.

let EMAIL_REGEXP = 
new RegExp (['^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()\[\]\\.,;:\s@\"]+)*)',
                    '|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.',
                    '[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+',
                    '[a-zA-Z]{2,}))$'].join(''));

лично я бы пошел на менее сложное регулярное выражение:

/\S+@\S+\.\S+/

конечно, меньше точный чем ваш текущий шаблон, но то, что вы пытаетесь достичь? Вы пытаетесь поймать случайные ошибки, которые могут ввести ваши пользователи, или вы беспокоитесь, что ваши пользователи могут попытаться ввести недопустимые адреса? Если это первый, я бы пошел на более простой шаблон. Если это последнее, некоторая проверка, ответив на электронное письмо, отправленное на этот адрес, может быть лучше выбор.

однако, если вы хотите использовать ваш текущий шаблон, было бы (ИМО) легче читать (и поддерживать!) путем построения его из более мелких подшаблонов, например:

var box1 = "([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)";
var box2 = "(\".+\")";

var host1 = "(\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])";
var host2 = "(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,})";

var regex = new RegExp("^(" + box1 + "|" + box2 + ")@(" + host1 + "|" + host2 + ")$");

чтобы избежать массиве join, вы также можете использовать следующий синтаксис:

var pattern = new RegExp('^(([^<>()[\]\.,;:\s@\"]+' +
  '(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@' +
  '((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|' +
  '(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$');