Группа захвата совпадений фиксированное количество раз - PullRequest
1 голос
/ 09 апреля 2020

У меня есть куча 5-буквенных строк. Для каждой строки я хотел бы найти соответствие, только если строка содержит 3 экземпляра одной буквы, то есть:

Case 1: 'aabbc'  ->  no match
Case 2: 'bbbcc'  ->  match 'bbb'
Case 3: 'ddcdc'  ->  match 'ddd'

Моя лучшая попытка регулярного выражения:

(.){1}(?!\1)*\1{1}(?!\1)*\1{1}

Это работает для случай 1 (где нет совпадений) и случай 2 (где 3 экземпляра смежны), но не для случая 3 (где 3 экземпляра разделены хотя бы одной другой буквой).

Есть ли регулярное выражение, которое будет работать для случая 3? В идеале я хотел бы также извлечь местоположения 3 совпадающих экземпляров из строки.

Ответы [ 3 ]

0 голосов
/ 09 апреля 2020

Вы можете использовать следующее регулярное выражение, чтобы определить, появляется ли один символ хотя бы три раза.

^.*(.).*\1.*\1

Демо

Это не проверяет, что символы буквы, но он работает с любыми символами. Чтобы ограничить использование букв, измените каждый . на [a-z] или [a-zA-Z], в зависимости от ситуации.

Чтобы увидеть, появляется ли один символ точно 3 раза, измените регулярное выражение на:

^(?!.*(.)(?:.*\1){3,}).*(.).*\2.*\2

Демо

^           # match beginning of line
(?!         # begin negative lookahead
  .*        # match 0+ chars
  (.)       # match a char in cap grp 2
  (?:.*\1)  # match 0+ chars followed by content of cap grp 1
            # in a non-cap grp
  {3,}      # execute non-cap grp 3+ times 
)           # end negative lookahead
.*          # match 0+ chars
(.)         # match char in cap grp 2
.*          # match 0+ chars
\2          # match content of cap grp 2
.*          # match 0+ chars
\2          # match content of cap grp 2
0 голосов
/ 09 апреля 2020

Приведенный ниже шаблон ловит то, что вам нужно, и должен охватывать крайние случаи. Первую группу захвата можно изменить, чтобы она представляла собой подмножество символов, которые необходимо искать, если имеется ограниченный список ожидаемых значений. Помещение \1 s в группы захвата означает, что вы должны быть в состоянии извлечь индекс групп захвата из матча через .start() (получение начального индекса группы захвата), выполняя вашу бонусную цель.

>>> pattern = r"(.).*(\1).*(\1)"
>>> x = re.search(pattern, "ababb")
>>> x.groups()
('b', 'b', 'b')
>>> x.start(1)
1
>>> x.start(2)
3
>>> x.start(3)
4
0 голосов
/ 09 апреля 2020

Я думаю, что шаблон ([a-z]).*?\1.*?\1 делает то, что вы хотите, хотя, вероятно, существуют крайние случаи, которые усложнят его.

Шаблон ищет строчную букву три раза, с 0 или более символами между их.

После этого вы можете извлечь только группы захвата, чтобы получить местоположения совпадений.

В данный момент шаблон ищет только строчные буквы, повторенные три раза, но вы можете изменить исходную группу захвата. - ([a-z]) - если вы хотите захватить что-то еще.

Демо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...