代码之家  ›  专栏  ›  技术社区  ›  Caveatrob

获取具有正则表达式匹配的所有子组

  •  3
  • Caveatrob  · 技术社区  · 15 年前

    给定字符串:

     © 2010 Women’s Flat Track Derby Association (WFTDA) 
    

    我想要:

    2010 -- Women's -- Flat
    Women's -- Flat -- Track
    Track -- Derby -- Association
    

    我正在使用regex:

    ([a-zA-Z]+)\s([A-Z][a-z]*)\s([a-zA-Z]+)
    

    它只会回来:

    s -- Flat -- Track
    
    2 回复  |  直到 15 年前
        1
  •  10
  •   Community Mohan Dere    9 年前

    这个问题并不简单,但要理解原因,您需要了解正则表达式引擎如何对字符串进行操作。

    让我们考虑一下模式 [a-z]{3} (a和z之间连续匹配3个字符)在目标字符串上 abcdef . 发动机从管柱左侧开始(在 a ),并看到 一 比赛 [a-z] ,所以它前进了一个位置。然后,它看到了 b 比赛 [a-z] 再次前进。最后,它看到了 c 匹配,再次前进(到之前 d )和回报 abc 作为匹配。

    如果引擎设置为返回多个匹配项,则它现在将再次尝试匹配,但它保留其位置信息(如上文所述,它将匹配并返回 def ).

    因为引擎已经过了 乙 在匹配时 abc公司 , bcd 不会被视为匹配。出于同样的原因,在您的表达式中,一旦一组单词匹配,引擎将永远不会将第一个匹配中的单词视为下一个匹配的一部分。


    为了解决这个问题,您需要使用 lookaheads 要收集后面出现在字符串中的匹配单词,请执行以下操作:

    var str = "2010 Women's Flat Track Derby Association",
        regex = /([a-z0-9']+)(?=\s+([a-z0-9']+)\s+([a-z0-9']+))/ig;
    
    while (match = regex.exec(str))
    {
        var group1 = match[1], group2 = match[2], group3 = match[3];
        document.write("Found match: " + group1 + " -- " + group2 + " -- " + group3 + "<br />\n");
    }
    

    这将导致:

    2010 -- Women's -- Flat
    Women's -- Flat -- Track
    Flat -- Track -- Derby
    Track -- Derby -- Association
    

    请参见 http://jsfiddle.net/jRgXm/ .

    正则表达式搜索您似乎定义为单词的内容 ([a-z0-9']+) ,并将其捕获到子组1中,然后使用lookahead(这是一个零宽度断言,因此它不会前进引擎的光标),该断言将下两个单词捕获到子组2和3中。

    然而 ,如果您使用的是实际的Javascript引擎,则 必须 RegExp.exec 循环查看结果(请参见 this question 讨论原因)。我不知道UltraEdit的引擎是如何实现的,但希望它可以进行全局搜索,还可以收集子组。

        2
  •  1
  •   josh.trow    15 年前

    我正在使用一些通用的正则表达式测试程序,所以我不能保证它会为您工作,但是。。。

    ([A-Z0-9][\w’]+)\s([A-Z][\w]+)\s([A-Z][\w]+)
    

    以数字或大写字母开头的三个单词,后跟字母/数字或由空格分隔的那个时髦的撇号。对我有用。

    编辑:我想你可以循环,重复JS中的matcher,我从来没有用过它。