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

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

var pattern = /^(([^<>()[\]\\.,;:\[email protected]\"]+(\.[^<>()[\]\\.,;:\[email protected]\"]+)*)|(\".+\"))@((\[[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,}))$/;

Ответ 1

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

var myRE = new RegExp (['^(([^<>()[\]\\.,;:\\[email protected]\"]+(\\.[^<>(),[\]\\.,;:\\[email protected]\"]+)*)',
                        '|(\\".+\\"))@((\\[[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 т.д.).

(() => {
  const createRegExp = (str, opts) => 
    new RegExp(str.raw[0].replace(/\s/gm, ""), opts || "");
  const yourRE = createRegExp'
    ^(([^<>()[\]\\.,;:\[email protected]\"]+(\.[^<>()[\]\\.,;:\[email protected]\"]+)*)|
    (\".+\"))@((\[[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);
})();

Ответ 2

Расширение ответа @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)

Ответ 3

Использование строк в 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$/
]);

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

Ответ 4

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

let EMAIL_REGEXP = 
new RegExp (['^(([^<>()[\\]\\\.,;:\\[email protected]\"]+(\\.[^<>()\\[\\]\\\.,;:\\[email protected]\"]+)*)',
                    '|(".+"))@((\\[[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(''));

Ответ 5

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

/\[email protected]\S+\.\S+/

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

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

var box1 = "([^<>()[\]\\\\.,;:\[email protected]\"]+(\\.[^<>()[\\]\\\\.,;:\[email protected]\"]+)*)";
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 + ")$");

Ответ 6

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

var pattern = new RegExp('^(([^<>()[\]\\.,;:\[email protected]\"]+' +
  '(\.[^<>()[\]\\.,;:\[email protected]\"]+)*)|(\".+\"))@' +
  '((\[[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,}))$');

Ответ 7

Вы можете просто использовать строковую операцию.

var pattenString = "^(([^<>()[\]\\.,;:\[email protected]\"]+(\.[^<>()[\]\\.,;:\[email protected]\"]+)*)|"+
"(\".+\"))@((\[[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,}))$";
var patten = new RegExp(pattenString);

Ответ 8

Здесь есть хорошие ответы, но для полноты кто-то должен упомянуть основную особенность Javascript наследования с цепочкой прототипов. Нечто подобное иллюстрирует идею:

RegExp.prototype.append = function(re) {
  return new RegExp(this.source + re.source, this.flags);
};

let regex = /[a-z]/g
.append(/[A-Z]/)
.append(/[0-9]/);

console.log(regex); //=> /[a-z][A-Z][0-9]/g