Регулярное выражение Python: совпадать только если шаблон повторяется n раз - PullRequest
1 голос
/ 15 апреля 2019

У меня есть строка: Name Mass From To Disulphide bond -2.02 97 144 Disulphide bond -2.02 111 158 Disulphide bond -2.02 121 174 Disulphide bond -2.02 125 176 Disulphide bond -2.02 85 174 Disulphide bond -2.02 10 176

Я хочу вытащить кортежи (97,144), (111,158), (121,174), (125,176), (85,174), (10,176) (т.е.пары чисел после -2,02 в каждом случае).

Я хочу сопоставлять только строки, которые соответствуют этому точному количеству повторяющихся комбинаций (т. е. где точно повторяется одна и та же комбинация слов «Дисульфидная связь -2,02 XX»).6 раз).В файле будут другие строки с точно таким же шаблоном, но повторяющиеся более или менее раз, чем 6 раз (например, другая строка в файле может быть 'Name Mass From To Disulphide bond -2.02 97 144 Disulphide bond -2.02 111 158 Disulphide bond -2.02 121 174', я не хочу соответствовать этому).

Я изначально писал регулярное выражение, например:

six_regex = re.search(r'Name  Mass  From  To  Disulphide bond  -2.02  ([\d]+)  ([\d]+)  Disulphide bond  -2.02  ([\d]+)  ([\d]+)  Disulphide bond  -2.02  ([\d]+)  ([\d]+)  Disulphide bond  -2.02  ([\d]+)  ([\d]+)  Disulphide bond  -2.02  ([\d]+)  ([\d]+)  Disulphide bond  -2.02  ([\d]+)  ([\d]+)',mod_line)

Мне интересно, есть ли способ написать регулярное выражение, например:

ix_regex = re.search(r' Disulphide bond  -2.02  ([\d]+)  ([\d]+)  ',mod_line)

, где я добавляю 'matchтолько если вышеприведенная фраза соответствует 6 раз '.

Я использовал regex101.com для работы с чем-то вроде Disulphide bond -2.02 ([\d]+) ([\d\s]+){6}, потому что я читал в другом месте на stackoverflow, что размещение числа в скобках может быть решением;но я, кажется, не получаю совпадений.

Может ли кто-нибудь посоветовать более аккуратное регулярное выражение, где мне нужно сопоставить повторяющийся шаблон n раз, чтобы он совпадал.

Ответы [ 3 ]

3 голосов
/ 15 апреля 2019

Вы можете использовать этот код в Python:

>>> import re
>>> s = 'Name  Mass  From  To  Disulphide bond  -2.02  97  144  Disulphide bond  -2.02  111  158  Disulphide bond  -2.02  121  174  Disulphide bond  -2.02  125  176  Disulphide bond  -2.02  85  174  Disulphide bond  -2.02  10  176'
>>> arr = re.findall(r'(?<=Disulphide bond  -2.02  )(\d+)  (\d+)', s)
>>> if len(arr) == 6:
...     print arr
...
[('97', '144'), ('111', '158'), ('121', '174'), ('125', '176'), ('85', '174'), ('10', '176')]

Код Демо

** Подробная информация о RegEx: &&

  • (?<=Disulphide bond -2.02 ): посмотрите за выражением, чтобы утверждать, что мы дали строку слева от текущей позиции
  • (\d+) (\d+): сопоставить 2 числа, разделенные 2 пробелами в 2 разных группах захвата
2 голосов
/ 15 апреля 2019

У вас есть правильная идея с квантификатором {6}.

Ваша проблема не в группировке ((?:) - не выбрана группа) правильного шаблона.

Name Mass From To (?:Disulphide bond -2\.02 ([\d]+) ([\d]+)\s*){6} должен добиться цели.

Объяснение

  • Name Mass From To - начало строки.
  • (?: - открытие группы без выбора.
  • Disulphide bond -2\.02 ([\d]+) ([\d]+)\s* - шаблон, который вы хотите повторить
  • ) - закрыть группу без выбора.
  • {6} - повторить группу без выбора шесть раз.
1 голос
/ 15 апреля 2019

Если я правильно понимаю, вы можете использовать

reg1 = re.compile(r"(?:\s?Disulphide bond  -2.02  [\d]+  [\d]+\s?){6}")
matches = reg1.findall(your_string)

reg2 = re.compile(r"Disulphide bond  -2.02  ([\d]+)  ([\d]+)")
pairs = [reg2.findall(el) for el in matches]

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

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