Regex - утверждение вложенного просмотра вперед

предположим, мы хотим сопоставить все one (s) между <out>...</out> в этом тексте (параметр: точка соответствует всем):

<out>hello!</out>
<nx1>home one</nx1>
<nx2>living</nx2>
<out>one text
text one continues 
and at last here ends one</out>
<m2>dog one</m2>
<out>bye!</out>

допустим, мы используем этот шаблон:

one(?=(?:(?!<out>).)*</out>)

Я очень признателен, если кто-нибудь объяснит, как механизм регулярных выражений обрабатывает этот шаблон шаг за шагом и где он будет (позиция в исходном тексте) на каждом этапе обработки; (что-то вроде accept @ Полезное объяснение Тимом Пицкером этого вопроса: Regex - прогнозируемое утверждение)


person wiki    schedule 29.05.2014    source источник
comment
Предоставленный шаблон не будет соответствовать всем one (s) между тегами out. например. третья строка, содержащая несколько one (s)   -  person Dhrubajyoti Gogoi    schedule 29.05.2014


Ответы (2)


Многие , которые автоматически объясняют, что делает ваше регулярное выражение, символ за символом.

Идея, лежащая в основе этого, заключается в том, что вы хотите проверить, что за one следует </out>, запрещая вводить новый тег out: если есть ...</out> подписчиков, и мы не ввели новую структуру <out>...</out>, мы знаем, что мы уже внутри нее .

Таким образом, регулярное выражение будет соответствовать one, если за ним следует </out> и если между ними нет <out>.

Работа выполняется (?:(?!<out>).)*: . подходит только в том случае, если это не первый < в <out>. Таким образом, мы можем подняться до </out>, только используя символы, отличные от этого <, за которым следует out>.


Улучшение скорости будет:

one(?=(?:[^<]*+|<(?!out>))*+</out>)

Переход внутрь отрицательного просмотра вперед на каждый символ значительно увеличивает стоимость сопоставления этого символа. Здесь [^<]*+ будет соответствовать непосредственно до следующего подозрительного <, и мы выполняем отрицательную предварительную проверку только тогда, когда это необходимо.

person Robin    schedule 29.05.2014
comment
Спасибо за ваш ответ; Я не понимал роли . и * в (?:(?!<out>).)*; так что движок проверяет 5 символов (длина <out>) с того места, где он сейчас находится (сразу после one (line4)), и видит, что это не то (это: текст), а теперь .: что это разрыв строки ??? - person wiki; 29.05.2014
comment
@wiki: не забывайте, что упреждающий просмотр имеет нулевую ширину и не потребляют персонажей! (?!<out>). на abc будет соответствовать a: мы начинаем за первым символом, и (?!<out>) проверяет, не являются ли первые 5 символов <out>. Нет, поэтому регулярное выражение продолжается (мы все еще до a), и . соответствует a. При повторении шаблона с * регулярное выражение выполняет предварительную проверку каждого символа перед его сопоставлением. Это понятнее? - person Robin; 29.05.2014

Вот объяснение из здесь:

NODE                     EXPLANATION
--------------------------------------------------------------------------------
  one                      'one'
--------------------------------------------------------------------------------
  (?=                      look ahead to see if there is:
--------------------------------------------------------------------------------
    (?:                      group, but do not capture (0 or more
                             times (matching the most amount
                             possible)):
--------------------------------------------------------------------------------
      (?!                      look ahead to see if there is not:
--------------------------------------------------------------------------------
        <out>                    '<out>'
--------------------------------------------------------------------------------
      )                        end of look-ahead
--------------------------------------------------------------------------------
      .                        any character except \n
--------------------------------------------------------------------------------
    )*                       end of grouping
--------------------------------------------------------------------------------
    </out>                   '</out>'
--------------------------------------------------------------------------------
  )                        end of look-ahead
person Amit Joki    schedule 29.05.2014
comment
спасибо, но RegexBuddy умеет намного лучше! Я знаю, что (?! - это отрицательное утверждение! но я хочу знать, что это работает в вышеупомянутом шаблоне; проверьте объяснение @Tim Pietzcker - person wiki; 29.05.2014