2013-11-14 3 views
0

Почему мой шаблон производит этот результат? Я ожидаю, что он найдет ATG, затем последовательность из 3, которая не включает TAA.regex negative lookahead assertion, похоже, не работает

In [102]: s = 'GATGCCTAAG' 
In [103]: pat = re.compile("(ATG((\w\w\w)*)(?!TAA))") 
In [104]: pat.findall(s) 
Out[104]: [('ATGCCTAAG', 'CCTAAG', 'AAG')] 

ответ

3

findall метод возвращает список совпадений. Если шаблон содержит группы захвата, то каждое совпадение является кортежем строк, соответствующих каждой группе захвата в шаблоне.

От the documentation:

Возврата непересекающихся матчей pattern в string, в виде списка строк. string сканируется слева направо, а совпадения возвращаются в найденном порядке. Если одна или несколько групп присутствуют в шаблоне, верните список групп; это будет список кортежей, если шаблон имеет более одной группы. Пустые совпадения включаются в результат, если они не касаются начала другого матча.

Ваш шаблон содержит три группы захвата. Группы вложены. Первой (и самой внешней) группой является весь шаблон, (ATG((\w\w\w)*)(?!TAA)). Вторая группа - ((\w\w\w)*). Третья группа - (\w\w\w).

Обратите внимание, что отрицательное утверждение, (?!TAA), is не группа захвата.

По сути, ваш рисунок говорит, что он соответствует кодону ATG, за которым следует как можно больше кодонов, но резервное копирование двух кодонов, если совпадение остановится на кодоне TAA. Поскольку * жадный, ваш шаблон будет соответствовать кодону посередине. Он отклонит только кодон TAA (и кодон до этого), если TAA встречается в конце входной строки.

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

Вы можете отметить группу в качестве не-захвата с использованием (?:...), как это:

In [5]: pat = re.compile("(?:ATG(?:(?:\w\w\w)*)(?!TAA))") 

Если шаблон не содержит захватив группы, затем findall возвращается каждый матч как одну строку, вместо того, как кортеж.

In [6]: pat.findall(s) 
Out[6]: ['ATGCCTAAG'] 

Если вы хотите остановиться в первойTAA, но идти до конца строки, если нет TAA на всех, вы должны проверить каждый кодон, наложив свое отрицательное опережения утверждение внутри повторение:

pat = re.compile("ATG(?:(?!TAA)\w\w\w)*") 

Это утверждает, на каждый кодон после первоначального ATG, что оно не должно совпадать с TAA кодоном.

Если вы хотите остановиться на первом TAA кодона, даже если кодон не совпадает с ATG, вы можете сделать это следующим образом:

In [7]: pat = re.compile("ATG(?:(?!.{0,2}TAA)\w\w\w)*") 

In [8]: pat.findall(s) 
Out[8]: ['ATG'] 

In [10]: pat.findall('ATGCCTGAATATAAG') 
Out[10]: ['ATGCCTGAA'] 
+0

как заставить искать только для всего шаблона, но не подшаблоны? – ashim

+0

Я обновил свой ответ. –

+0

(?! TAA) не должен включать TAA, но в конечном итоге он включен, почему? – ashim

0

Кроме того, в модуле повторно, * включает в себя, возможно, ноль этого элемента, в дополнение к тому, что написал @rob mayoff.

Из документов:

* 

Причины результирующий RE, чтобы соответствовать 0 или более повторений предшествующего RE, как много повторений, как возможно. ab * будет соответствовать 'a', 'ab', или 'a', за которым следует любое число 'b'.

0

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

Смежные вопросы