У меня очень длинное регулярное выражение, которое я хочу разбить на несколько строк в своем коде 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,}))$/;
javascript
regex
jslint
expression
readability
Ник Сумейко
источник
источник
/\S+@\S+\.\S+/
?Ответы:
Вы можете преобразовать его в строку и создать выражение, вызвав
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(''));
Примечания:
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` ^(([^<>()[\]\\.,;:\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); })();
источник
new RegExp
- отличный способ для многострочных регулярных выражений. Вместо объединения массивов вы можете просто использовать оператор конкатенации строк:var reg = new RegExp('^([a-' + 'z]+)$','i');
//
) и вставить его в качестве строкового аргумента в конструктор RegExp. Это связано с тем, что символы обратной косой черты используются при вычислении строкового литерала . Пример:/Hey\sthere/
нельзя заменить наnew RegExp("Hey\sthere")
. Вместо этого его следует заменить на.new RegExp("Hey\\sthere")
Обратите внимание на дополнительную обратную косую черту! Следовательно, я предпочитаю просто оставлять длинный литерал регулярного выражения на одной длинной строкеRegExp
объект так, чтобы его было легче понять.Расширяя ответ @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)
источник
combineRegex = (...regex) => new RegExp(regex.map(r => r.source).join(""))
Использование:combineRegex(/regex1/, /regex2/, ...)
Использование строк в
new RegExp
неудобно, потому что вы должны избегать всех обратных косых черт. Вы можете писать регулярные выражения меньшего размера и объединять их.Давайте разделим это регулярное выражение
Позже мы будем использовать функцию, чтобы сделать вещи красивее
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$/ ]);
Поскольку это требует затрат, попробуйте создать реальное регулярное выражение только один раз, а затем используйте его.
источник
multilineRegExp([/a|b/, /c|d])
приводит/a|bc|d/
, а вы имели в виду(a|b)(c|d)
.Благодаря чудесному миру шаблонных литералов теперь вы можете писать большие, многострочные, хорошо прокомментированные и даже семантически вложенные регулярные выражения в ES6.
//build regexes without worrying about // - double-backslashing // - adding whitespace for readability // - adding in comments let clean = (piece) => (piece .replace(/((^|\n)(?:[^\/\\]|\/[^*\/]|\\.)*?)\s*\/\*(?:[^*]|\*[^\/])*(\*\/|)/g, '$1') .replace(/((^|\n)(?:[^\/\\]|\/[^\/]|\\.)*?)\s*\/\/[^\n]*/g, '$1') .replace(/\n\s*/g, '') ); window.regex = ({raw}, ...interpolations) => ( new RegExp(interpolations.reduce( (regex, insert, index) => (regex + insert + clean(raw[index + 1])), clean(raw[0]) )) );
Используя это, теперь вы можете писать такие регулярные выражения:
let re = regex`I'm a special regex{3} //with a comment!`;
Выходы
/I'm a special regex{3}/
А как насчет многострочного?
'123hello' .match(regex` //so this is a regex //here I am matching some numbers (\d+) //Oh! See how I didn't need to double backslash that \d? ([a-z]{1,3}) /*note to self, this is group #2*/ `) [2]
Выходы
hel
, аккуратные!«Что, если мне действительно нужно искать новую строку?», Ну тогда используйте
\n
глупо!Работаю над моими Firefox и Chrome.
Хорошо, "как насчет чего-нибудь посложнее?"
Конечно, вот фрагмент JS-парсера, деструктурирующего объект, над которым я работал :
regex`^\s* ( //closing the object (\})| //starting from open or comma you can... (?:[,{]\s*)(?: //have a rest operator (\.\.\.) | //have a property key ( //a non-negative integer \b\d+\b | //any unencapsulated string of the following \b[A-Za-z$_][\w$]*\b | //a quoted string //this is #5! ("|')(?: //that contains any non-escape, non-quote character (?!\5|\\). | //or any escape sequence (?:\\.) //finished by the quote )*\5 ) //after a property key, we can go inside \s*(:|) | \s*(?={) ) ) ((?: //after closing we expect either // - the parent's comma/close, // - or the end of the string \s*(?:[,}\]=]|$) | //after the rest operator we expect the close \s*\} | //after diving into a key we expect that object to open \s*[{[:] | //otherwise we saw only a key, we now expect a comma or close \s*[,}{] ).*) $`
Он выводит
/^\s*((\})|(?:[,{]\s*)(?:(\.\.\.)|(\b\d+\b|\b[A-Za-z$_][\w$]*\b|("|')(?:(?!\5|\\).|(?:\\.))*\5)\s*(:|)|\s*(?={)))((?:\s*(?:[,}\]=]|$)|\s*\}|\s*[{[:]|\s*[,}{]).*)$/
И запустить его с небольшой демонстрацией?
let input = '{why, hello, there, "you huge \\"", 17, {big,smelly}}'; for ( let parsed; parsed = input.match(r); input = parsed[parsed.length - 1] ) console.log(parsed[1]);
Успешно выводит
{why , hello , there , "you huge \"" , 17 , {big ,smelly } }
Обратите внимание на успешный захват строки в кавычках.
Я тестировал его в Chrome и Firefox, отлично работает!
Если интересно, вы можете проверить, что я делал , и его демонстрацию .
Хотя он работает только в Chrome, потому что Firefox не поддерживает обратные ссылки или именованные группы. Так что обратите внимание, что пример, приведенный в этом ответе, на самом деле является кастрированной версией, и его можно легко обмануть, приняв недопустимые строки.
источник
Здесь есть хорошие ответы, но для полноты картины следует упомянуть основную функцию 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
источник
В приведенном выше регулярном выражении отсутствуют некоторые черные косые черты, которые не работают должным образом. Итак, я отредактировал регулярное выражение. Обратите внимание на это регулярное выражение, которое работает на 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(''));
источник
Чтобы избежать массива
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,}))$');
источник
Лично я бы выбрал менее сложное регулярное выражение:
Конечно, это менее точно чем ваш текущий шаблон, но чего вы пытаетесь достичь? Вы пытаетесь отловить случайные ошибки, которые могут ввести ваши пользователи, или вас беспокоит, что ваши пользователи могут попытаться ввести недопустимые адреса? Если это первое, я бы выбрал более простой узор. Если это последнее, то лучшим вариантом может быть проверка путем ответа на электронное письмо, отправленное на этот адрес.
Однако, если вы хотите использовать свой текущий шаблон, было бы (IMO) легче читать (и поддерживать!), Создавая его из более мелких подшаблонов, например:
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 + ")$");
источник
Вы можете просто использовать строковую операцию.
var pattenString = "^(([^<>()[\]\\.,;:\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,}))$"; var patten = new RegExp(pattenString);
источник
Я попытался улучшить ответ коруна, инкапсулируя все и реализовав поддержку разделения групп захвата и наборов символов, что сделало этот метод гораздо более универсальным.
Чтобы использовать этот фрагмент, вам нужно вызвать вариативную функцию
combineRegex
, аргументы которой являются объектами регулярного выражения, которые вам нужно объединить. Его реализацию можно найти внизу.Группы захвата не могут быть разделены таким образом напрямую, так как некоторые части останутся только с одной круглой скобкой. Ваш браузер не сработает за исключением.
Вместо этого я просто передаю содержимое группы захвата внутри массива. Скобки добавляются автоматически при
combineRegex
обнаружении массива.Кроме того, кванторы должны за чем-то следовать. Если по какой-то причине регулярное выражение необходимо разделить перед квантификатором, вам нужно добавить пару круглых скобок. Они будут удалены автоматически. Дело в том, что пустая группа захвата бесполезна, и квантификаторам есть на что ссылаться. Тот же метод можно использовать для таких вещей, как группы без захвата (
/(?:abc)/
становится[/()?:abc/]
).Лучше всего это объяснить на простом примере:
var regex = /abcd(efghi)+jkl/;
станет:
var regex = combineRegex( /ab/, /cd/, [ /ef/, /ghi/ ], /()+jkl/ // Note the added '()' in front of '+' );
Если вы должны разделить наборы символов, вы можете использовать объекты (
{"":[regex1, regex2, ...]}
) вместо массивов ([regex1, regex2, ...]
). Содержимое ключа может быть любым, если объект содержит только один ключ. Обратите внимание, что вместо того()
, чтобы использовать в]
качестве фиктивного начала, если первый символ можно интерпретировать как квантификатор. Т.е./[+?]/
становится{"":[/]+?/]}
Вот фрагмент и более полный пример:
function combineRegexStr(dummy, ...regex) { return regex.map(r => { if(Array.isArray(r)) return "("+combineRegexStr(dummy, ...r).replace(dummy, "")+")"; else if(Object.getPrototypeOf(r) === Object.getPrototypeOf({})) return "["+combineRegexStr(/^\]/, ...(Object.entries(r)[0][1]))+"]"; else return r.source.replace(dummy, ""); }).join(""); } function combineRegex(...regex) { return new RegExp(combineRegexStr(/^\(\)/, ...regex)); } //Usage: //Original: console.log(/abcd(?:ef[+A-Z0-9]gh)+$/.source); //Same as: console.log( combineRegex( /ab/, /cd/, [ /()?:ef/, {"": [/]+A-Z/, /0-9/]}, /gh/ ], /()+$/ ).source );
источник
Отличный ответ @Hashbrown направил меня на верный путь. Вот моя версия, тоже вдохновленная этим блогом .
function regexp(...args) { function cleanup(string) { // remove whitespace, single and multi-line comments return string.replace(/\s+|\/\/.*|\/\*[\s\S]*?\*\//g, ''); } function escape(string) { // escape regular expression return string.replace(/[-.*+?^${}()|[\]\\]/g, '\\$&'); } function create(flags, strings, ...values) { let pattern = ''; for (let i = 0; i < values.length; ++i) { pattern += cleanup(strings.raw[i]); // strings are cleaned up pattern += escape(values[i]); // values are escaped } pattern += cleanup(strings.raw[values.length]); return RegExp(pattern, flags); } if (Array.isArray(args[0])) { // used as a template tag (no flags) return create('', ...args); } // used as a function (with flags) return create.bind(void 0, args[0]); }
Используйте это так:
regexp('i')` //so this is a regex //here I am matching some numbers (\d+) //Oh! See how I didn't need to double backslash that \d? ([a-z]{1,3}) /*note to self, this is group #2*/ `
Чтобы создать этот
RegExp
объект:/(\d+)([a-z]{1,3})/i
источник