2016-02-25 5 views
5

Я использую python 2.6 и пытаюсь найти кучу повторяющихся символов в строке, скажем, связку n, например. nnnnnnnABCnnnnnnnnnDEF. В любом месте строки число n может быть переменной.Regex, найти шаблон только в середине строки

Если я построить регулярное выражение как это:

re.findall(r'^(((?i)n)\2{2,})', s),

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

re.findall(r'(((?i)n)\2{2,}$)', s),

я могу обнаружить те только в конце последовательности. Но как насчет посередине?

Сначала я думал использовать re.findall(r'(((?i)n)\2{2,})', s) и двух предыдущих регулярных выражений (-ices?), Чтобы проверить длину возвращаемого списка и наличие n-х либо в начале или в конце строки и делать логические тесты , но он быстро стал уродливым беспорядком if-else.

Затем я попытался re.findall(r'(?!^)(((?i)n)\2{2,})', s), который, кажется, Exlude начало только штраф, но (?!$) или (?!\z) в конце регулярного выражения только исключает в ABCnnnn последнюю n. Наконец, я попробовал re.findall(r'(?!^)(((?i)n)\2{2,})\w+', s), который, кажется, работает иногда, но я получаю странные результаты в других. Мне кажется, что мне нужен взгляд или взгляд, но я не могу обвести вокруг себя голову.

+0

Try [ '(<^?!) ((П) \ 2 {2})' (<п?!) ($?!)] (HTTPS: //regex101.com/r/dY3cZ9/1). Вам не нужна встроенная версия модификатора без учета регистра '(? I)', просто используйте 're.I' (так как весь шаблон будет нечувствительным к регистру в любом случае при использовании' (? I) '). –

+0

что не так с '((? I) n) \ 1 {2,}' https://regex101.com/r/oT6vZ1/1? –

+0

или '\ B (?

ответ

3

Вместо использования сложного регулярного выражения, чтобы отказаться от сопоставления символов верхнего и нижнего n. Как более вещий подхода вы можете strip() тогда ваша строка найти всю последовательность n с использованием re.findall() и простого регулярного выражение:

>>> s = "nnnABCnnnnDEFnnnnnGHInnnnnn" 
>>> import re 
>>> 
>>> re.findall(r'n{2,}', s.strip('n'), re.I) 
['nnnn', 'nnnnn'] 

Примечания: re.I является Игнорированием случая флага, который делает регулярное выражение двигатель соответствует символам верхнего регистра и нижнего регистра.

+0

'n' - последовательность символов. Думаю, вам нужно их «re.sub». –

+0

@ WiktorStribiżew Не имеет значения, 'str.strip()' удалит все ведущие и завершающие вхождения переданного аргумента. – Kasramvd

+0

@ WiktorStribiżew: кажется, что 'n' является персонажем, см. Последние комментарии. –

1

Примечание: Это решение предполагает n может представлять собой последовательность некоторых символов. Для более эффективных альтернатив, когда n всего 1 символ, см. Другие ответы здесь.

Вы можете использовать

(?<!^)(?<!n)((n)\2{2,})(?!$)(?!n) 

Смотрите regex demo

Регулярное выражение будет соответствовать этому повторяющееся подряд n s (игнорируя случай может быть достигнуто с re.I флагом), которые не в начале ((?<!^)) или конец ((?!$)) строки и не ранее ((?!n)) или после ((?<!n)) еще n.

(?<!^)(?<!n) представляет собой последовательность из 2 просмотра назад: (?<!^) означает не потребляет следующий рисунок, если предшествуют с началом строки. (?<!n) отрицательный lookbehind означает, что не потребляет следующий шаблон, если ему предшествует n. Отрицательные образы (?!$) и (?!n) имеют схожие значения: (?!$) не соответствует совпадению, если после текущей позиции происходит конец строки, а (?!n) не будет соответствовать, если n происходит после текущей позиции в строке (то есть сразу после сопоставления всех последовательных n s .. условия lookaround все должны быть выполнены, поэтому мы только получаем самые сокровенные матчи

См IDEONE demo:

import re 
p = re.compile(r'(?<!^)(?<!n)((n)\2{2,})(?!$)(?!n)', re.IGNORECASE) 
s = "nnnnnnnABCnnnnnNnnnnDEFnNn" 
print([x.group() for x in p.finditer(s)]) 
2

с «п» является символом (и не подшаблон), вы можете просто использование:

re.findall(r'(?<=[^n])nn+(?=[^n])(?i)', s) 

или лучше:

re.findall(r'n(?<=[^n]n)n+(?=[^n])(?i)', s) 
Смежные вопросы