Regex 如何捕获多个重复组?
我需要捕获相同模式的多个组。假设我有以下字符串:Regex 如何捕获多个重复组?,regex,swift,nsregularexpression,regex-greedy,regex-group,Regex,Swift,Nsregularexpression,Regex Greedy,Regex Group,我需要捕获相同模式的多个组。假设我有以下字符串: HELLO,THERE,WORLD 我写了下面的模式 ^(?:([A-Z]+),?)+$ 我想让它做的是,捕捉每一个单词,第一组是:“你好”,第二组是“那里”,第三组是“世界”,我的正则表达式实际上只捕捉最后一个单词,即“世界” 我正在测试我的正则表达式,我想将它与Swift一起使用(也许Swift中有一种方法可以以某种方式获得中间结果,这样我就可以使用它们了?) 更新:我不想使用split。我现在只需要了解如何捕获与模式匹配的所有组,而不仅
HELLO,THERE,WORLD
我写了下面的模式
^(?:([A-Z]+),?)+$
我想让它做的是,捕捉每一个单词,第一组是:“你好”,第二组是“那里”,第三组是“世界”,我的正则表达式实际上只捕捉最后一个单词,即“世界”
我正在测试我的正则表达式,我想将它与Swift一起使用(也许Swift中有一种方法可以以某种方式获得中间结果,这样我就可以使用它们了?)
更新:我不想使用
split
。我现在只需要了解如何捕获与模式匹配的所有组,而不仅仅是最后一组。模式中有一组,您只能在该组中获得一个精确结果。如果您的捕获组被模式重复(您在周围的非捕获组上使用了+
量词),则只存储与之匹配的最后一个值
必须使用语言的正则表达式实现函数来查找模式的所有匹配项,然后必须删除非捕获组的锚和量词(也可以省略非捕获组本身)
或者,展开您的正则表达式,并让模式包含每个要在结果中获得的组的一个捕获组:
^([A-Z]+),([A-Z]+),([A-Z]+)$
仅提供答案中第2段的附加示例。我不确定对你来说,在一场比赛中获得三个小组比在一个小组中获得三场比赛有多重要。例如,在groovy中:
def subject = "HELLO,THERE,WORLD"
def pat = "([A-Z]+)"
def m = (subject =~ pat)
m.eachWithIndex{ g,i ->
println "Match #$i: ${g[1]}"
}
Match #0: HELLO
Match #1: THERE
Match #2: WORLD
我想你需要这样的东西
b="HELLO,THERE,WORLD"
re.findall('[\w]+',b)
Python3中的哪个将返回
['HELLO', 'THERE', 'WORLD']
阅读之后,我想介绍一个可能的微小改进:
您可以生成与n
单词匹配的regexp,只要您的n
是预先确定的。例如,如果我想匹配1到3个单词,regexp:
([A-Z]+)(?:,([A-Z]+)(?:,([A-Z]+))(?:,([A-Z]+)$
将下列句子与一组、两组或三组进行匹配
HELLO,LITTLE,WORLD
HELLO,WORLD
HELLO
您可以看到有关此正则表达式的详细说明
正如我所说的,使用您喜欢的语言为您想要的任何组生成这个regexp非常容易。由于我不是一个敏捷的人,这里有一个ruby示例:
def make_regexp(组_regexp,计数:3,分隔符:“,”)
regexp_str=“^(#{group_regexp})”
(计数-1)次。每次
regexp_str+=“(?:#{delimiter}(#{group_regexp}))”
结束
regexp_str+=“$”
返回regexp_str
结束
放置make_regexp(“[A-Z]+”)
话虽如此,我还是建议不要使用正则表达式。在这种情况下,还有许多其他很棒的工具,从简单的
拆分,到一些标记化模式,都取决于您的需要。嗯,正则表达式不是其中之一。例如,在ruby中,我会使用类似于str.split(“,”)
或str.scan(/[A-Z]+/)
的东西,我知道我的答案来得晚,但今天我遇到了,我用以下方法解决了它:
^(([A-Z]+),)+([A-Z]+)$
因此,第一组([A-Z]+),)+
将匹配所有重复的模式,但最后一组([A-Z]+)
将匹配最后一组。无论字符串中有多少重复的组,这都是动态的。您实际上有一个捕获组将匹配多次。不是多个捕获组
javascript(js)解决方案:
let string=“你好,汤姆”;
设myRegexp=/([A-Z]+),?/g;//随意修改
让match=myRegexp.exec(字符串);//js函数,输出如下所述
while(match!=null){//在匹配中循环
console.log(match[1]);//对每个匹配执行任何操作
match=myRegexp.exec(字符串);//查找下一个匹配项
}
对不起,不是Swift,只是用最接近的语言证明概念
// JavaScript POC. Output:
// Matches: ["GOODBYE","CRUEL","WORLD","IM","LEAVING","U","TODAY"]
let str = `GOODBYE,CRUEL,WORLD,IM,LEAVING,U,TODAY`
let matches = [];
function recurse(str, matches) {
let regex = /^((,?([A-Z]+))+)$/gm
let m
while ((m = regex.exec(str)) !== null) {
matches.unshift(m[3])
return str.replace(m[2], '')
}
return "bzzt!"
}
while ((str = recurse(str, matches)) != "bzzt!") ;
console.log("Matches: ", JSON.stringify(matches))
注意:如果您真的要使用此选项,您将使用regex match函数给出的匹配位置,而不是字符串替换。关键区别在于重复捕获的组,而不是捕获重复的组
正如您已经发现的,不同之处在于重复捕获的组只捕获最后一次迭代。捕获重复的组将捕获所有迭代
在PCRE(PHP)中:
由于所有捕获都在组1中,因此您只需要$1
进行替换
我使用了此正则表达式的以下一般形式:
(((?:{{RE}})+)
举例
设计一个与列表的每个特定元素相匹配的正则表达式,而不是将列表作为一个整体。使用/g应用它
循环遍历匹配项,从任何垃圾中清除它们,例如混合在其中的列表分隔符。您可能需要另一个正则表达式,也可以使用简单的替换子字符串方法
示例代码是JS,抱歉:)这个想法必须足够清楚
const string = 'HELLO,THERE,WORLD';
// First use following regex matches each of the list items separately:
const captureListElement = /^[^,]+|,\w+/g;
const matches = string.match(captureListElement);
// Some of the matches may include the separator, so we have to clean them:
const cleanMatches = matches.map(match => match.replace(',',''));
console.log(cleanMatches);
为什么不在,
上拆分?为什么不使用[A-Z]+
或[^,]+
来捕获结果Rock321987,我已经更新了输入字符串。我需要精确地提取遵循上述模式的字符串。我需要让所有的组都符合模式,而不仅仅是最后一组。我想知道如何处理regex.rock321987,还有什么不清楚的?我需要字符串中的每个单词都是匹配的组,但我的模式只捕获最后一个(“世界”)。使用此模式查找所有匹配项如何调整此值以考虑不同数量的字符串?e、 你好,世界,你好,我的世界。我正在寻找一个表达式来处理这两个示例,并为更长的字符串提供内置的灵活性arrays@Chris这是不可能一概而论的。正如答案所述,一个捕获组只能捕获一件事情,并且无法创建动态数量的捕获组。这不是问题的解决方案。问题不是匹配字符串,而是捕获所有组。T
Match 1, Group 1. 0-5 HELLO
Match 2, Group 1. 6-11 THERE
Match 3, Group 1. 12-20 BRUTALLY
Match 4, Group 1. 21-26 CRUEL
Match 5, Group 1. 27-32 WORLD
const string = 'HELLO,THERE,WORLD';
// First use following regex matches each of the list items separately:
const captureListElement = /^[^,]+|,\w+/g;
const matches = string.match(captureListElement);
// Some of the matches may include the separator, so we have to clean them:
const cleanMatches = matches.map(match => match.replace(',',''));
console.log(cleanMatches);