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.com (в PHP
поскольку эмулятор не обеспечивает такую же функциональность для 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
Дайте мне знать, если вы добьетесь того, чего хотите!