正则表达式匹配重复字符
比如我有一个字符串:
aacbbbqq
我想要得到以下的匹配结果:
(aa, c, bbb, qq)
我知道我可以写一些像这样的东西:
([a]+)|([b]+)|([c]+)|...
但是我觉得这样写不好看,所以我在寻找更好的解决方案。我想要用正则表达式来解决这个问题,而不是自己写有限状态机。
7 个回答
26
itertools.groupby
不是正则表达式,也不是自己写的东西。:-) 这是来自 Python 文档的一句话:
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
26
一般来说
这里的窍门是先匹配你想要的字符范围中的一个字符,然后确保匹配到这个字符的所有重复:
>>> matcher= re.compile(r'(.)\1*')
这段代码会匹配任何单个字符(.
),然后匹配这个字符的重复出现(\1*
),如果有的话。
对于你的输入字符串,你可以得到想要的输出:
>>> [match.group() for match in matcher.finditer('aacbbbqq')]
['aa', 'c', 'bbb', 'qq']
注意:由于使用了匹配组,re.findall
可能无法正确工作。
其他范围
如果你不想匹配 任何 字符,可以相应地修改正则表达式中的 .
:
>>> matcher= re.compile(r'([a-z])\1*') # only lower case ASCII letters
>>> matcher= re.compile(r'(?i)([a-z])\1*') # only ASCII letters
>>> matcher= re.compile(r'(\w)\1*') # ASCII letters or digits or underscores
>>> matcher= re.compile(r'(?u)(\w)\1*') # against unicode values, any letter or digit known to Unicode, or underscore
可以用它来检查 u'hello²²'
(Python 2.x)或 'hello²²'
(Python 3.x):
>>> text= u'hello=\xb2\xb2'
>>> print('\n'.join(match.group() for match in matcher.finditer(text)))
h
e
ll
o
²²
在处理非Unicode字符串或字节数组时,使用 \w
可能会受到影响,如果你先调用了 locale.setlocale
。
47
你可以用这个来匹配:(\w)\1*