是否可以做这样的事情?
var pattern = /some regex segment/ + /* comment here */
/another segment/;
或者我是否必须使用新的RegExp()
语法并连接字符串?我更喜欢使用文字,因为代码更加不言而喻,简洁明了。
答案 0 :(得分:169)
以下是如何在不使用正则表达式文字语法的情况下创建正则表达式。这使您可以在它成为正则表达式对象之前进行任意字符串操作:
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(/(.)(?=.*\1)/g, "");
var regex3 = new RegExp(expression_one.source + expression_two.source, flags);
// regex3 is now /foobar/gy
只是让表达式一和二是文字字符串而不是文字正则表达式,这更加冗长。
答案 1 :(得分:21)
只是随机连接正则表达式对象可能会产生一些不良副作用。改为使用RegExp.source:
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
这也使您能够使用标准RegExp标志保留先前RegExp中的正则表达式标志。
答案 2 :(得分:13)
我不太同意“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的可选参数。
在我的情况下,我运行的问题是^和$在几个表达式中使用我试图连接在一起!这些表达式是整个程序使用的语法过滤器。现在我不想将它们中的一些用在一起来处理PREPOSITIONS的情况。 我可能必须“切片”源以删除开始和结束^(和/或)$ :) 干杯,亚历克斯。
答案 3 :(得分:6)
问题如果正则表达式包含像\ 1这样的反向匹配组。
var r = /(a|b)\1/ // Matches aa, bb but nothing else.
var p = /(c|d)\1/ // Matches cc, dd but nothing else.
然后只是连接源不起作用。实际上,两者的结合是:
var rp = /(a|b)\1(c|d)\1/
rp.test("aadd") // Returns false
解决方案: 首先我们计算第一个正则表达式中匹配组的数量,然后对于第二个正则表达式中的每个反向匹配标记,我们将它增加匹配组的数量。
function concatenate(r1, r2) {
var count = function(r, str) {
return str.match(r).length;
}
var numberGroups = /([^\\]|^)(?=\((?!\?:))/g; // Home-made regexp to count groups.
var offset = count(numberGroups, r1.source);
var escapedMatch = /[\\](?:(\d+)|.)/g; // Home-made regexp for escaped literals, greedy on numbers.
var r2newSource = r2.source.replace(escapedMatch, function(match, number) { return number?"\\"+(number-0+offset):match; });
return new RegExp(r1.source+r2newSource,
(r1.global ? 'g' : '')
+ (r1.ignoreCase ? 'i' : '')
+ (r1.multiline ? 'm' : ''));
}
测试:
var rp = concatenate(r, p) // returns /(a|b)\1(c|d)\2/
rp.test("aadd") // Returns true
答案 4 :(得分:3)
提供:
/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">$1</span>')
.replace(/(\btrue|false\b)/g, '<span class="bool">$1</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">$1</span>')
.replace(/\$/g, '<span class="dollar">$</span>')
.replace(/([\[\](){}.:;,+\-?=])/g, '<span class="ponctuation">$1</span>')
答案 5 :(得分:1)
你必须使用新的RegExp! - )
答案 6 :(得分:1)
不,不支持文字方式。你必须使用RegExp。
答案 7 :(得分:1)
最好尽可能经常使用文字语法。它更短,更清晰,你不需要逃脱引号或双逃逸反冲。来自“Javascript Patterns”,Stoyan Stefanov 2010.
但使用New可能是连接的唯一方法。
我会避免评估。它不安全。
答案 8 :(得分:1)
使用带有2个参数的构造函数,避免跟踪问题&#39; /&#39;:
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
答案 9 :(得分:1)
您可以执行以下操作:
function concatRegex(...segments) {
return new RegExp(segments.join(''));
}
段将是作为单独参数传入的字符串(而不是正则表达式文字)。
答案 10 :(得分:1)
您可以从文字和RegExp类中连接正则表达式源:
var xxx = new RegExp(/abcd/);
var zzz = new RegExp(xxx.source + /efgh/.source);
答案 11 :(得分:1)
对我来说更简单的方法是将源连接起来,例如:
a = /\d+/
b = /\w+/
c = new RegExp(a.source + b.source)
c值将导致:
/ \ d + \ w + /
答案 12 :(得分:-3)
我更喜欢使用eval('your expression')
,因为它不会在/
的每一端/
添加='new RegExp'
。