【问题标题】:Getting all subgroups with a regex match使用正则表达式匹配获取所有子组
【发布时间】:2010-11-16 22:09:44
【问题描述】:

给定字符串:

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

我想要:

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

我正在使用正则表达式:

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

它只是返回:

s -- Flat -- Track

【问题讨论】:

  • 对不起 - 它是 ultraedit JS,所以可能 javascript 可以工作。

标签: javascript regex


【解决方案1】:

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

让我们考虑目标字符串abcdef 上的模式[a-z]{3}(匹配a 和z 之间的3 个连续字符)。引擎从字符串的左侧(a 之前)开始,发现a[a-z] 匹配,因此它前进一个位置。然后,它看到b 匹配[a-z] 并再次前进。最后,它看到c 匹配,再次前进(到d 之前)并返回abc 作为匹配。

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

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


为了解决这个问题,您需要使用lookaheads 内的捕获组来收集字符串中稍后出现的匹配词:

var str = "2010 Women's Flat Track Derby Association",
    regex = /([a-z0-9']+)(?=\s+([a-z0-9']+)\s+([a-z0-9']+))/ig,
    match;

while (match = regex.exec(str))
{
    var group1 = match[1], group2 = match[2], group3 = match[3];
    console.log("Found match: " + group1 + " -- " + group2 + " -- " + group3);
}

这会导致:

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

http://jsfiddle.net/jRgXm/查看此操作。

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

但是,如果您使用的是实际的 Javascript 引擎,您必须 RegExp.exec 并循环查看结果(有关原因的讨论,请参阅 this question)或使用新的matchAll 方法(ES2020)。我不知道 UltraEdit 的引擎是如何实现的,但希望它可以进行全局搜索并收集子组。

为了完整起见,这是上面使用 ES2020' matchAll 的示例(每个返回数组中的第一个元素是总匹配,然后是后续元素是捕获组):

const str = "2010 Women's Flat Track Derby Association";
const regex = /([a-z0-9']+)(?=\s+([a-z0-9']+)\s+([a-z0-9']+))/ig;

console.log([...str.matchAll(regex)]);

【讨论】:

    【解决方案2】:

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

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

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

    编辑:我假设你可以循环遍历,在我从未使用过的 JS 中重复匹配器。

    【讨论】:

    • 看起来它可能正在使用 Perl。你的镜头得到了更多,但不是全部。
    • 行不通;正则表达式匹配不会重叠。有关更多信息,请参阅我的答案。
    猜你喜欢
    • 1970-01-01
    • 2013-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多