Python: регулярные выражения при получении повторяющегося набора чисел

Я работаю с файлом, который является записью Genbank (похоже на это)

Моя цель - извлечь числа в строке CDS, например:

    CDS             join(1200..1401,3490..4302)

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

     CDS            join(1200..1401,1550..1613,1900..2010,2200..2250,
                 2300..2660,2800..2999,3100..3333)

Я использую это регулярное выражение:

     import re
     match=re.compile('\w+\D+\W*(\d+)\D*')
     result=match.findall(line)
     print(result)

Это дает мне правильные цифры, а также номера из остальной части файла, как

 gene            complement(3300..4037)

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

Я собираюсь использовать числа, чтобы напечатать кодирующую часть базовой последовательности.

2 ответа

Вы могли бы использовать сильно улучшенный regex модуль Мэтью Барнетта (который обеспечивает \G функциональность). С этим вы могли бы придумать следующий код:

import regex as re
rx = re.compile("""
            (?:
                CDS\s+join\(    # look for CDS, followed by whitespace and join(
                |               # OR
                (?!\A)\G        # make sure it's not the start of the string and \G 
                [.,\s]+         # followed by ., or whitespace
            )
            (\d+)               # capture these digits
                """, re.VERBOSE)

string = """
         CDS            join(1200..1401,1550..1613,1900..2010,2200..2250,
                     2300..2660,2800..2999,3100..3333)
"""

numbers = rx.findall(string)
print numbers
# ['1200', '1401', '1550', '1613', '1900', '2010', '2200', '2250', '2300', '2660', '2800', '2999', '3100', '3333']

\G удостоверяется, что механизм регулярных выражений ищет следующий матч в конце последнего матча.
Посмотреть демо на regex101.comPHP поскольку эмулятор не обеспечивает такую ​​же функциональность для Python [он использует оригинал re модуль]).

Крайне низкое решение (если вам разрешено использовать только re модуль), будет использовать lookarounds:

(?<=[(.,\s])(\d+)(?=[,.)])

(?<=) положительный взгляд позади, в то время как (?=) это позитивный взгляд вперед, ознакомьтесь с демонстрацией этого подхода на regex101.com. Знайте, хотя может быть несколько ложных срабатываний.

Следующие re шаблон может работать:

>>> match = re.compile(\s+CDS\s+\w+\([^\)]*\))

Но вам нужно позвонить findall на всем тексте, а не на одной строке за раз.

Вы можете использовать круглые скобки, чтобы просто взять цифры:

>>> match = re.compile(\s+CDS\s+\w+\(([^\)]*)\))
>>> match.findall(stuff)
1200..1401,3490..4302       # Numbers only

Дайте мне знать, если вы добьетесь того, чего хотите!

Другие вопросы по тегам