Регулярное выражение для поиска подстроки - PullRequest
4 голосов
/ 16 июня 2020

Я пытаюсь найти все вхождения подстроки, используя регулярное выражение. Подстрока состоит из трех частей, начинается с одной или нескольких «А», за которыми следует одна или несколько «N» и заканчивается одной или несколькими буквами «А». Пусть строка 'AAANAANABNA' , и если я проанализирую строку, я должен получить две подстроки 'AAANAA' и 'AANA' в качестве вывода. Итак, я попробовал приведенный ниже код.

import regex as re
reg_a='A+N+A+'
s='AAANAANABNA'
sub_str=re.findall(reg_a,s,overlapped=True)
print(sub_str)

И я получаю следующий результат:

['AAANAA', 'AANAA', 'ANAA', 'AANA', 'ANA']

Но мне нужен результат как

['AAANAA', 'AANA']

То есть конечные А первого совпадения должны быть ведущими А следующего совпадения. Как я могу это понять?

Ответы [ 3 ]

5 голосов
/ 16 июня 2020

Убедитесь, что слева нет A:

>>> reg_a='(?<!A)A+N+A+'
>>> print( re.findall(reg_a,s,overlapped=True) )
['AAANAA', 'AANA']

(?<!A)A+N+A+ соответствует

  • (?<!A) - отрицательный просмотр назад, соответствующий местоположению, которое не предшествует сразу A
  • A+ - один или несколько A s
  • N+ - один или несколько N s
  • A+ - один или несколько A s

Обратите внимание, что вы также можете использовать re для получения совпадений:

>>> import re
>>> re_a = r'(?=(?<!A)(A+N+A+))'
>>> print( re.findall(re_a, s) )
['AAANAA', 'AANA']
4 голосов
/ 16 июня 2020

Вот более простой способ добиться этого с помощью модуля re. Нам просто нужен просмотр вперед для 1+ конечных A s и нужно использовать 2 группы захвата:

>>> import re
>>> s = 'AAANAANABNA'
>>> [''.join(x) for x in re.findall(r'(A+N+)(?=(A+))', s)]
['AAANAA', 'AANA']

RegEx Demo

4 голосов
/ 16 июня 2020

Один из вариантов - использовать отрицательный просмотр назад с группой захвата внутри положительного просмотра без перекрытия. re.findall вернет значение группы захвата.

(?=(?<!A)(A+N+A+))
  • (?= Положительный просмотр вперед, утверждение, что справа -
    • (?<!A) Отрицательный просмотр вперед, утверждение то, что слева, не A
    • (A+N+A+) Соответствует вашему шаблону
  • ) Close lookahead

Regex демо | Python демонстрация

import re
s = "AAANAANABNA"
pattern = r"(?=(?<!A)(A+N+A+))"
print(re.findall(pattern, s))

Вывод

['AAANAA', 'AANA']

Или, как предлагает @ anubhava , отделите ретроспективный просмотр от просмотра вперед:

(?<!A)(?=(A+N+A+))

Regex demo | Python демо

...