Python正则表达式分割多个匹配

时间:2017-07-05 19:15:12

标签: python regex split

我正在尝试将包含2个不同字符序列的字符串拆分成组。如果我们假设字符为ab,则分组的纯文本规则为:

  • 群组由0 + a组成,后跟1 + b
  • 以下所有a都包含在下一组中,除非我们在该词的末尾。

例如:处理tests后,目标是分成expected组。

tests = ['abab',
    'ababab',
    'aabab',
    'aababa',
    'aba',
    'baba']

expected = [['ab','ab'],
    ['ab','ab','ab'],
    ['aab','ab'],
    ['aab','aba'],
    ['aba'],
    ['b','aba']]

我得到的最接近的是:

import re

# filter() returns iterator not list in Python 3 
def testing(s):
    return list(filter(None, re.compile('(a*b+a*(?=$))').split(s)))

output = [testing(s) for s in tests]

output

[['ab', 'ab'], ['abab', 'ab'], ['aab', 'ab'], ['aab', 'aba'], ['aba']]

哪一组在1-2组中表现良好,但对于大于此组的组则不然,这意味着我的正则表达式需要改进。我应该重新考虑这种方法吗?我可以用for循环做一些暴力但是希望有更优雅的东西。

N.B。:This post让我相信.split()可能不是这里的方式,但到目前为止我已经获得了最好的结果。

2 个答案:

答案 0 :(得分:3)

我相信你走在了正确的轨道上。但是,你的正则表达式比你想象的还要多。您的测试用例并未涵盖所有可能的情况,因此您没有意识到这一点。

由于您有几个特殊情况,您应该单独处理它们。例如,最后一个输入是特殊情况,因为它匹配aba。同样,单独列出其他内容并将其与|一起加入。您也可以使用re.findall,它更清洁。

tests = ['abab',
        'ababab',
        'aabab',
        'aababa',
        'aba',
        'baba']

def testing(s):
    return re.findall('(?:a*b+a+$)|(?:a*b+)|(?:b+a+)', s)

output = [testing(s) for s in tests]   
print(output)

输出:

[['ab', 'ab'], ['ab', 'ab', 'ab'], ['aab', 'ab'], ['aab', 'aba'], ['aba'], ['b', 'aba']]

答案 1 :(得分:1)

这给出了测试数据的正确结果:

tests = ['abab',
'ababab',
'aabab',
'aababa',
'aba',
'baba',
'abba']

for s in tests:
    r = re.findall("(?:a*b+a*$)|(?:a*b+)",s)
    print(r)

结果:

['ab', 'ab']
['ab', 'ab', 'ab']
['aab', 'ab']
['aab', 'aba']
['aba']
['b', 'aba']
['abba']