Ответ 1
Вы можете сопоставить это с помощью: (\w)\1*
Например, у меня есть строка:
aacbbbqq
В результате я хочу иметь следующие совпадения:
(aa, c, bbb, qq)
Я знаю, что могу написать что-то вроде этого:
([a]+)|([b]+)|([c]+)|...
Но я думаю, что я уродлив и ищу лучшего решения. Я ищу решение для регулярного выражения, а не самозаписывающиеся конечные машины.
Вы можете сопоставить это с помощью: (\w)\1*
itertools.groupby
не является RexExp, но он не является самозаписываемым.:-) Цитата из python docs:
# [list(g) for k, g in groupby('AAAABBBCCD')] --> AAAA BBB CC D
Фокус в том, чтобы соответствовать одному char диапазона, который вы хотите, а затем убедитесь, что вы сопоставляете все повторения одного и того же символа:
>>> 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
²²
\w
для строк, не относящихся к Unicode/bytearrays, может быть изменен, если вы впервые выпустили вызов locale.setlocale
.
Это будет работать, см. рабочий пример здесь: http://www.rubular.com/r/ptdPuz0qDV
(\w)\1*
Метод findall будет работать, если вы захватите обратную ссылку следующим образом:
result = [match[1] + match[0] for match in re.findall(r"(.)(\1*)", string)]
Вы можете использовать:
re.sub(r"(\w)\1*", r'\1', 'tessst')
Вывод будет:
'test'