子字符串,最多3个字符中的2个

时间:2019-02-12 19:59:19

标签: python regex

我正在尝试编写一个正则表达式,以匹配包含['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*)+,但效果不是很好。正则表达式有可能吗?

1 个答案:

答案 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))消除。