Паттерн (ABC)+ — повторение группы ABC один или более раз.
s = "XYZABCABCABCXYZ"
re.findall(r'(ABC)+', s) # ['ABC'] — возвращает последнюю группу!
# Чтобы получить всю цепочку:
re.findall(r'(?:ABC)+', s) # ['ABCABCABC'] — (?:...) не захватывает
В примере (?:ABC)+ квантификатор + применяется ко всей группе ABC, но поскольку группа незахватывающая, re.findall() возвращает всё найденное совпадение целиком, а не содержимое группы. Это полезно, когда скобки нужны для структурирования выражения, но захват отдельных фрагментов не требуется.
Пример 1: (?:ABC)*(?:AB?)?
s = "XYZABCABCABXYZABCAYZ"
re.findall(r'(?:ABC)*(?:AB?)?', s) # много пустых...
Проблема: Этот паттерн создает множество пустых совпадений, потому что оба квантификатора * и ? делают совпадение необязательным. Паттерн может совпасть с пустой строкой в любой позиции:
-
(?:ABC)* — ноль или больше повторений ABC
-
(?:AB?)? — опционально A или AB
-
Оба элемента необязательны, поэтому паттерн совпадает везде, включая пустые позиции между символами
Пример 2: A(?:BCA)*B?C?
re.findall(r'A(?:BCA)*B?C?', s)
Логика: Более строгий паттерн, требующий обязательного начала с A:
-
A — обязательная буква A (якорь паттерна)
-
(?:BCA)* — ноль или больше повторений BCA (переставленный фрагмент)
-
B?C? — опционально B и/или C для неполного последнего фрагмента
Недостаток: Паттерн использует BCA вместо ABC, что меняет логику разбора и может работать некорректно для исходной задачи.
Пример 3: (?:ABC)+A?B?
re.findall(r'(?:ABC)+A?B?', s)
Оптимальное решение:
-
(?:ABC)+ — одно или больше повторений полного фрагмента ABC (обязательно хотя бы один)
-
A?B? — опционально добавляются A или AB для неполного последнего фрагмента
-
Квантификатор + гарантирует, что паттерн найдет только реальные цепочки, начинающиеся с хотя бы одного полного ABC, без пустых совпадений
Этот вариант находит цепочки типа ABC, ABCABC, ABCABCA, ABCABCAB и т.д., что соответствует задаче поиска последовательностей с возможно неполным последним фрагментом.