我正在尝试编写一个正则表达式,以匹配包含['a', 'b', 'c']
中最多2个字符重复的字符串中的所有子字符串
因此,像abcccbaaa
这样的字符串应具有以下匹配项:
ab
bc
bcc
bccc
cc
ccc
cccb
ba
baa
baaa
到目前为止,我所拥有的是:a+a*|a+b*|a+c*|b+a*|b+b*|b+c*|c+a*|c+b*|c+c*
但这与abab
之类的字符串不匹配。我还尝试过包装每个单独的组合,如下所示:(a+a*)+
,但效果不是很好。正则表达式有可能吗?
答案 0 :(得分:0)
您要查找的表达式是:(a + | b + | c +){2}
问题在于re.findall()不会与匹配模式重叠,所以:
re.findall("(a+|b+|c+){2}","abcccbaaa")
将仅找到连续(不重叠)的匹配项:“ ab”,“ cccb”和“ aaa”。 (即,由于第一个“ b”匹配项是“ ab”匹配项的一部分,因此不将其视为“ bc”匹配项)
为了获得所有重叠的模式,您将必须在字符串上迭代执行re.match(),删除每个匹配项第一个字符之前的字符,并在其余匹配项上执行re.match()直至找到没有更多的匹配。您还需要对较大的匹配项进行递归搜索,因为它们也可能包含较小的匹配模式(例如bccc包含bcc和bc)。最后,您可能希望从结果中消除重复项(例如ccc实际上是两个重叠的cc模式)。
我认为您不能在单个正则表达式中执行此操作,但可以在迭代函数中执行此操作:
import re
def multiMatch(pattern,string):
result = []
match = re.match(pattern,string)
while match:
subString = string[match.start():match.end()]
result.append(subString)
result += multiMatch(pattern,subString[:-1]) # see note below
string = string[match.start()+1:]
match = re.match(pattern,string)
return list(set(result))
sorted(multiMatch("(a+|b+|c+){2}","abcccbaaa"))
>>> ['aa', 'aaa', 'ab', 'ba', 'baa', 'baaa', 'bc', 'bcc', 'bccc', 'cb', 'cc', 'ccb', 'ccc', 'cccb']
注意:此时,您只需要从subString的开头检查较小的模式。我很懒,只是简单地递归地调用该函数,但这并不是最佳选择,因为它将生成子匹配项,该子匹配项将再次被主循环捕获,只是被list(set(result))消除。