Как я могу объединить литералы регулярных выражений в JavaScript?
можно ли сделать что-то подобное?
var pattern = /some regex segment/ + /* comment here */
/another segment/;
или я должен использовать новый RegExp() синтаксис и конкатенация строки? Я бы предпочел использовать литерал, поскольку код является более очевидным и кратким.
11 ответов:
вот как создать регулярное выражение без использования синтаксиса литерала регулярного выражения. Это позволяет выполнять манипуляции со строками арбитра, прежде чем он станет объектом регулярного выражения:
var segment_part = "some bit of the regexp"; var pattern = new RegExp("some regex segment" + /*comment here */ segment_part + /* that was defined just now */ "another segment");Если у вас есть два литерала регулярных выражений, вы можете фактически объединить их с помощью этого метода:
var regex1 = /foo/g; var regex2 = /bar/y; var flags = (regex1.flags + regex2.flags).split("").sort().join("").replace(/(.)(?=.*)/g, ""); var regex3 = new RegExp(expression_one.source + expression_two.source, flags); // regex3 is now /foobar/gyЭто просто более многословно, чем просто выражение одна и две строковые литералы вместо литералов регулярных выражений.
просто случайным образом связывая регулярные выражения объекты может иметь некоторые негативные побочные эффекты. Используйте регулярное выражение.источник вместо:
var r1 = /abc/g; var r2 = /def/; var r3 = new RegExp(r1.source + r2.source, (r1.global ? 'g' : '') + (r1.ignoreCase ? 'i' : '') + (r1.multiline ? 'm' : '')); var m = 'test that abcdef and abcdef has a match?'.match(r3); // m should contain 2 matchesЭто также даст вам возможность сохранить флаги регулярных выражений из предыдущего регулярного выражения, используя стандартные флаги регулярных выражений.
Я не совсем согласен с вариантом" eval".
var xxx = /abcd/; var yyy = /efgh/; var zzz = new RegExp(eval(xxx)+eval(yyy));даст "/ / abcd// efgh//", что не является предполагаемым результатом.
используя источник как
var zzz = new RegExp(xxx.source+yyy.source);даст "/ abcdefgh / " и это правильно.
логически нет необходимости оценивать, вы знаете свое выражение. Вам просто нужен его источник или как он написан не обязательно его значение. Что касается флагов, вам просто нужно использовать необязательный аргумент RegExp.
в моем ситуация, я бегу в вопросе ^ и $ используется в нескольких выражениях я пытаюсь объединить вместе! Эти выражения являются грамматическими фильтрами, используемыми в программе. Теперь я не хочу использовать некоторые из них вместе, чтобы справиться со случаем предлогов. Возможно, мне придется "нарезать" источники, чтобы удалить начало и конец ^ (и / или) $ :) Твое Здоровье, Алекс.
при условии, что:
- вы знаете, что вы делаете в ваше регулярное выражение;
- у вас есть много регулярных выражений, чтобы сформировать шаблон, и они будут использовать тот же флаг;
- вы найдете его более читаемым, чтобы разделить ваши небольшие фрагменты шаблона в массив;
- вы также хотите иметь возможность комментировать каждую часть для следующего dev или себя позже;
- вы предпочитаете визуально упростить ваше регулярное выражение, как
/this/g, а неnew RegExp('this', 'g');- это нормально для вас соберите регулярное выражение в дополнительный шаг, а не иметь его в одном куске с самого начала;
затем вы можете написать так:
var regexParts = [ /\b(\d+|null)\b/,// Some comments. /\b(true|false)\b/, /\b(new|getElementsBy(?:Tag|Class|)Name|arguments|getElementById|if|else|do|null|return|case|default|function|typeof|undefined|instanceof|this|document|window|while|for|switch|in|break|continue|length|var|(?:clear|set)(?:Timeout|Interval))(?=\W)/, /($|jQuery)/, /many more patterns/ ], regexString = regexParts.map(function(x){return x.source}).join('|'), regexPattern = new RegExp(regexString, 'g');затем вы можете сделать что-то вроде:
string.replace(regexPattern, function() { var m = arguments, Class = ''; switch(true) { // Numbers and 'null'. case (Boolean)(m[1]): m = m[1]; Class = 'number'; break; // True or False. case (Boolean)(m[2]): m = m[2]; Class = 'bool'; break; // True or False. case (Boolean)(m[3]): m = m[3]; Class = 'keyword'; break; // $ or 'jQuery'. case (Boolean)(m[4]): m = m[4]; Class = 'dollar'; break; // More cases... } return '<span class="' + Class + '">' + m + '</span>'; })в моем конкретном случае (код-зеркальный редактор) гораздо проще выполнить одно большое регулярное выражение, а не много замен, как показано ниже, поскольку каждый раз, когда я заменяю html-тег для обертывания выражения, следующий шаблон будет сложнее нацелить, не затрагивая сам html-тег (и без хорошего lookbehind это, к сожалению, не поддерживается в javascript):
.replace(/(\b\d+|null\b)/g, '<span class="number"></span>') .replace(/(\btrue|false\b)/g, '<span class="bool"></span>') .replace(/\b(new|getElementsBy(?:Tag|Class|)Name|arguments|getElementById|if|else|do|null|return|case|default|function|typeof|undefined|instanceof|this|document|window|while|for|switch|in|break|continue|var|(?:clear|set)(?:Timeout|Interval))(?=\W)/g, '<span class="keyword"></span>') .replace(/$/g, '<span class="dollar">$</span>') .replace(/([\[\](){}.:;,+\-?=])/g, '<span class="ponctuation"></span>')
было бы предпочтительно использовать литеральный синтаксис как можно чаще. Он короче, более разборчив, и вам не нужны escape-кавычки или двойные отступы. Из "Javascript Patterns", Стоян Стефанов 2010.
но использование New может быть единственным способом конкатенации.
Я бы избегал эвала. Это не безопасно.
используйте конструктор с 2 парами и избегайте проблемы с трейлингом'/':
var re_final = new RegExp("\" + ".", "g"); // constructor can have 2 params! console.log("...finally".replace(re_final, "!") + "\n" + re_final + " works as expected..."); // !!!finally works as expected // meanwhile re_final = new RegExp("\" + "." + "g"); // appends final '/' console.log("... finally".replace(re_final, "!")); // ...finally console.log(re_final, "does not work!"); // does not work
вы могли бы сделать что-то вроде:
function concatRegex(...segments) { return new RegExp(segments.join('')); }сегменты будут строками (а не литералами регулярных выражений), передаваемыми в виде отдельных аргументов.
Я предпочитаю использовать
eval('your expression')потому что он не добавляет/на каждом конце/что='new RegExp'делает.
Comments