Javascript 正则表达式。如何从该字符串中获取多个匹配项?
我正在使用javascript正则表达式。 假设我有以下字符串:Javascript 正则表达式。如何从该字符串中获取多个匹配项?,javascript,regex,Javascript,Regex,我正在使用javascript正则表达式。 假设我有以下字符串: XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_2_YYY YYY_3_YYY 我想运行一个正则表达式,并用这个模式得到一个结果: Match1 1. XXX_1_XXX 2. YYY_1_YYY Match2 1. XXX_2_XXX 2. YYY_2_YYY Match3 1. XXX_3_XXX 2. YYY_3_YYY 我尝试过这方面的变化:
XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_2_YYY YYY_3_YYY
我想运行一个正则表达式,并用这个模式得到一个结果:
Match1
1. XXX_1_XXX
2. YYY_1_YYY
Match2
1. XXX_2_XXX
2. YYY_2_YYY
Match3
1. XXX_3_XXX
2. YYY_3_YYY
我尝试过这方面的变化:
/(XXX_(.)_XXX)(.)*?(YYY_\2_YYY)/g
但它只在第一场比赛时停止
有没有办法用正则表达式来实现这一点?或者我最好将其作为数组进行迭代?匹配是在字符串上进行迭代的,在上一个匹配结束后,正则表达式只搜索更多匹配。这保证了进度,因为空字符串可能导致无限循环 但您可以通过以下方式解决此问题:
var text = "XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_2_YYY YYY_3_YYY";
var re = /(XXX_(.)_XXX)(.)*?(YYY_\2_YYY)/;
while((m = re.exec(text)) !== null) {
alert(JSON.stringify(m));//the result (print)
//do something with m
text = text.substring(m.index+1); //this is not the same as /g
// "/g" would be text = text.substring(m.index+m[0].length+1);
}
该程序的工作原理如下:您不使用/g
修饰符,因此只进行一次匹配
.index
,并将字符串(包括)放到该点注意:必须考虑的另一个方面是,这不需要“全局”进展。字符串
XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY_3_YYY_2_YYY
(注意YYY|u YYYY
部分中的交换值)将给出相同的结果
regex101.com网站是找到正确正则表达式的绝佳资源。我准备了两个例子:
/([XY]{3}{[0-3]{[XY]{3})/g
将返回:
匹配11.[0-9]
XXX\u 1\u XXX
匹配2
1.[10-19]
XXX\u 2\u XXX
匹配3
1.[20-29]
XXX\u 3\u XXX
匹配4
1.[30-39]
YYY\u 1\u YYY
匹配5
1.[40-49]
YYY\u 2\u YYY
匹配6
1.[50-59]
YYY\u 3\u YYY
及
/(?:([XY]{3}{[0-3]{[XY]{3})([XY]{3}{[0-3]{[XY]{3}))/g
将返回:
匹配11.[0-9]
XXX\u 1\u XXX
2.[10-19]
XXX\u 2\u XXX
匹配2
1.[20-29]
XXX\u 3\u XXX
2.[30-39]
YYY\u 1\u YYY
匹配3
1.[40-49]
YYY\u 2\u YYY
2.[50-59]
YYY\u 3\u YYY
问题在于,在第一次匹配之后,正则表达式引擎的内部索引设置在“YYY_*\uyyy”之后 幸运的是,在循环中,您可以将该位置移到“XXX_*\u XXX”匹配后的右侧:
var s = 'XXX_1_XXX XXX_2_XXX XXX_3_XXX YYY_1_YYY YYY_2_YYY YYY_3_YYY';
var re = /(XXX_(\d)_XXX).*?(YYY_\2_YYY)/g;
while ((match = re.exec(s)) !== null) {
console.log(match[1], match[3]);
// move to start of last match plus length of first submatch
re.lastIndex = match.index + match[1].length;
}
输出
“XXX\u 1\u XXX”
“YYY_1_YYY”
“XXX_2_XXX”
“YYY_2_YYY”
“XXX_3_XXX”
“YYY_3_YYY”
您可以简单地剪切字符串中匹配开始的部分……在我看来,您不可能通过一个正则表达式一次性获得这些匹配。一旦您匹配了过去的某个内容,它就不会向后查找另一个匹配项。一次获取所有匹配项:/([XY]{3}{0-3].[XY]{3})/g
。演示:正则表达式的工作方式是,它尝试匹配某些内容,然后当设置g标志时,它在第一个匹配之后开始。在您的情况下,它在YYY_1_YYY
之后再次开始,显然没有匹配项。请问您试图解决的根本问题是什么?@Sumurai8:您可以通过实现一个(修改的)globalizer来绕过这个问题……这也会匹配字符串,比如XYX\u 1\u XYX
。如果存在这样的边缘情况,则正则表达式确实应该更新。它也不会根据请求将字符串分组为XXX_1_XXX
和YYY_1_YYY
,但如果在解析之前不进行排序,则正则表达式几乎不可能这样做。谢谢您的回答。但是我需要XXX和YYY在同一场比赛中。(数字相同的那些)您认为需要在同一个匹配中同时使用它们,但是如果您稍微更改第一个正则表达式,使匹配包含1_XXX
和1_YYY
,您只需对列表排序,这样就可以轻松地对它们进行分组。是的,谢谢,这就解决了问题。正如其他人所指出的,我遇到了麻烦,因为光标会在第一次匹配后启动。while循环解决了这个问题。@han4wluc:正如答案中所指出的,发生这种情况有一个很好的原因,如果可以匹配空字符串,您必须更加小心。我想,除了这不需要子字符串之外。另一件事是您使用group[1]
。在这个例子中,这将起作用,因为没有重叠,但在一般情况下,它可能会导致冲突。例如,对于<代码> /(AAA)/<代码> >代码> AAAA ON期望两个匹配。您不能总是考虑所有的角。代码>修复此“问题”。