2015-07-12 2 views
0

Эффект, который я хочу: сбой, если x не найден до y.Regex match all with delimiter

import re 

a = '''START aaaadkdklfje VALUE aaaadkdklfjeaaaadkdklfjeaaaadkdklfje aaaadkdklfjeaaaadkdklfjeaaaadkdklfjeaaaadkdklfjeaaaadkdklfjeaaaadkdklfje aaaadkdklfjeaaaadkdklfje   aaaadkdklfje 
aaaadkdklfje 
aaaadkdklfje condition a 
aaaadkdklfje 
aaaadkdklfje 
aaaadkdklfje condition b 
          aaaadkdklfje z 
          aaaadkdklfjeaaaadkdklfje  aaaadkdklfjeqqqsdddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddfsdfsdf 
condition c 

???kjij 
START...''' 

b = re.findall(r'START condition a (VALUE).+?condition b.+?condition c(?!START)', a, re.DOTALL) 
if b: 
    for x in b: 
     print x 

Я хочу, чтобы захватить value только тогда, когда condition s в своем текстовом блоке присутствуют. Без соответствия прошлому start.

Это единственный случай, который должен соответствовать:

start 
?, value, ?, condition a, ?, condition b, ?, condition C# i want the matching to be done only in here 
start 
... 

Не так:

start 
?, value, condition a, ? 
start 
?, value, ?, condition b, condition c 
start 
+2

вопрос неясно для меня .. –

+0

такой же здесь, я не понимаю вопрос –

+1

Если условия всегда находятся в одном порядке (a, b, c), или они могут иметь другой порядок (b, c, a) или (c, a, b)? –

ответ

1

Вы можете объединить несколько lookarounds для не пропуская START и поддержания последовательности условие:

(?s)START(?:(?!START|condition).)*?\b(VALUE)(?=(?:(?!START).)*?condition a(?:(?!START).)*?condition b(?:(?!START).)*?condition c) 

Test at regex101 но обратите внимание, t шляпа это ужасная работа:]

Это позволяет condition a condition a condition b condition c. Для того, чтобы исключительные условия, изменить condition a(?:(?!START).)*? и Bc части к condition a(?:(?!START|condition).)*? ...

+0

О, так между каждым выражением, он проверяет 'start' после каждого символа? Забавный – user193661

+0

@ user193661 вправо, он имеет очень низкую производительность! –

+0

используя '(? :(?! START | условие).) *?' Немного избыточно, потому что вы используете в то же время '| условие' * и * неживой квантификатор. Ваш шаблон будет лучше, если вы будете использовать '(? :(?! START | условие).) *' Или '(? :(? START).) *?' –

2

Другим способом состоит в использовании нескольких этапов:

  • вы разбить строку с `START`, чтобы получить список блоков
  • вас фильтрующие блоки, которые не имеют условий
  • , вы вставляете «СТАРТ» перед каждым элементом.
blocks = re.split(r'\bSTART\b', s) 
blocks = filter(lambda x: re.search(r'condition a.*?condition b.*?condition c', x), blocks[1:]) 
blocks = map(lambda x: 'START'+x, blocks) 

Примечание: если вы хотите, чтобы условия, чтобы быть после ключевого слова VALUE, добавить \bVALUE\b.*? в начале шаблона поиска.

+0

Ну, это будет лучше работать на больших входах! –

+1

@ Jonny5: Честно говоря, я действительно не знаю! –

+0

Я попробую профилировать два подхода и пост, который быстрее. – user193661