给定字符串:
© 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
最佳答案
这个问题并不简单,但要理解原因,您需要了解正则表达式引擎如何对您的字符串进行操作。
让我们考虑目标字符串 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 中,然后使用前瞻(是一个零宽度断言,因此它不会推进引擎的光标),它将接下来的两个词捕获到子组 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)]);
关于javascript - 使用正则表达式匹配获取所有子组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4199545/