Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 正则表达式。如何从该字符串中获取多个匹配项?_Javascript_Regex - Fatal编程技术网

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 我尝试过这方面的变化:

我正在使用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_(.)_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

    将返回:

    匹配1
    1.[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

    将返回:

    匹配1
    1.[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期望两个匹配。您不能总是考虑所有的角。代码>修复此“问题”。