Закаленный жадный токен – что отличает размещение точки до негативного взгляда

<table((?!).)* 

соответствует всем моим табличным тегам, однако,

 <table(.(?!))* 

не. Второй, кажется, имеет смысл, если я пытаюсь выписать выражение в словах, но я не могу понять первое.

Может кто-нибудь объяснить мне разницу?

Для справки я получил термин «Закаленный жадный токен» отсюда: http://www.rexegg.com/regex-quantifiers.html#tempered_greed

Поскольку Google возвращает этот SO-запрос поверх результатов для tempered greedy token , я чувствую себя обязанным предоставить более полный ответ.

Что такое закаленный жадный токен?

Упорядоченная лексическая ссылка rexegg.com довольно кратким:

В (?:(?!{END}).)* , Квантификатор * применяется к точке, но теперь она является закаленной точкой. Отрицательный lookahead (?!{END}) утверждает, что то, что следует за текущей позицией, не является строкой {END} . Поэтому точка никогда не сможет сопоставить открывающую скобку {END} , гарантируя, что мы не будем перепрыгивать через разделитель {END} .

Вот он: умеренный жадный токен – это своего рода отрицательный характерный class для последовательности символов (ср. Отрицательный class символов для одного символа ).

ПРИМЕЧАНИЕ . Разница между умеренным жадным токеном и отрицательным символьным classом заключается в том, что первый не соответствует тексту, отличному от самой последовательности, а является единственным символом , который не запускает эту последовательность. Ie (?:(?!abc|xyz).)+ будет соответствовать def в defabc , но будет соответствовать def и bc , потому что a запускает запрещенную последовательность abc , а bc – нет.

Это состоит из:

  • (?:...)* – количественная группа без захвата (это может быть группа захвата, но нет смысла захватывать каждый отдельный символ) (a * может быть + , это зависит от того, является ли пустая строка совпадением ожидается)
  • (?!...) – негативный взгляд, который фактически налагает ограничение на значение справа от текущего местоположения
  • . – (или любой (обычно одиночный) символ).

Тем не менее, мы всегда можем смягчить токен, используя чередование в негативном образе (например, (?!{(?:END|START|MID)}) ) или путем замены точки совпадения на отрицательный class символов (например (?:(?!START|END|MID)[^<>]) при попытке сопоставить текст только внутри тегов).

Размещение расходных частей

Обратите внимание, что нет упоминания о конструкции, в которой потребляемая часть (точка в исходном закаленном жадном токене) помещается перед записью. Ответ Avinash объясняет эту часть ясно: (.(?!))* сначала сопоставляет любой символ (но новую строку без модификатора DOTALL), а затем проверяет, не следует ли ему приводит к ошибке для соответствия e в

table

. Потребляемая часть ( . ) ДОЛЖНА быть размещена после закаливания .

Когда использовать умеренный алчный токен?

Rexegg.com дает представление:

  • Когда мы хотим сопоставить блок текста между разделителем 1 и разделителем 2 без промежуточной подстроки 3 (например, {START}(?:(?!{(?:MID|RESTART)}).)*?{END}
  • Когда мы хотим сопоставить блок текста, содержащий конкретный шаблон внутри, без переполнения последующих блоков (например, вместо ленивого сопоставления точек, как в
    .*?chair.*?

    , мы будем использовать что-то вроде

    (?:(?!chair|).)*chair(?:(?!
    ).)*

    ).

  • Когда мы хотим совместить кратчайшее окно между двумя строками. Lazy matching не поможет, когда вам нужно получить abc 2 xyz от abc 1 abc 2 xyz (см. abc.*?xyz и abc(?:(?!abc).)*?xyz ).

Проблема с производительностью

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

Скажем, мы хотим abc 2 xyz в abc 1 abc 2 xyz 3 xyz . Вместо проверки каждого символа между abc и xyz с помощью abc(?:(?!abc|xyz).)*xyz , мы можем пропустить все символы, которые не являются a или x с [^ax]* , а затем соответствуют всем a не сопровождаются bca(?!bc) ) и всеми x , не сопровождаемыми yzx(?!yz) ): abc[^ax]*(?:a(?!bc)[^ax]*|x(?!yz)[^ax]*)*xyz .

((?!).)* будет проверять, что этот конкретный символ, который будет согласован, не должен быть начальным символом в строке . Если да, то только он соответствует этому конкретному символу. * повторяет то же самое ноль или более раз.

(.(?!))* соответствует любому символу, только если за ним не следует , ноль или более раз. Таким образом, это будет соответствовать всем символам внутри тега таблицы excpet последнего символа, так как за последним символом следует . И следующий шаблон утверждает, что в конце матча должен быть тег закрывающей таблицы. Это приведет к сбою матча.

См. Здесь

Умеренный жадный токен на самом деле просто означает:

«матч, но только до точки»

как ты это делаешь:

вы помещаете токен, который вы не хотите сопоставлять, как отрицательный lookahead (?!notAllowedToMatch) перед точкой . (соответствовать какой-либо одной вещи), то вы повторяете эту вещь со звездой * :

((?!notAllowedToMatch).)*

как это работает:

«смотреть и есть один» снова и снова, перемещая один символ во времени слева направо через входную строку до тех пор, пока не увидите запрещенную последовательность (или конец строки), после чего совпадение остановится.

Более подробный ответ Wiktor хорош, я просто подумал, что более простое объяснение было в порядке.

  • Используя grep в R, чтобы найти строки как целые слова (но не строки как часть слов)
  • Обнаружить и извлечь url из строки?
  • Разделить строку на предложения
  • mod_rewrite: заменить подчеркивания тире
  • Как заменить регулярное выражение в MySQL?
  • Признавательная способность «современных» регулярных выражений
  • Список всех специальных символов, которые должны быть экранированы в регулярном выражении
  • Regex только для чисел
  • Вставка запятых в числовую строку
  • Возможно ли выполнить проверку данных в MySQL с использованием регулярного выражения
  • Регулярные выражения с повторяющимися символами
  • Interesting Posts

    Почему malloc + memset работает медленнее, чем calloc?

    jQuery – Получить ширину элемента, если он не отображается (Дисплей: Нет)

    Windows 7: Командная строка не будет записывать компакт-диск в сетевой сопоставленный диск

    Динамически генерировать запросы LINQ

    window.onbeforeunload не работает в хроме

    Как перебрать HashMap с помощью JSTL forEach?

    Каковы эквивалентные версии IPV6 для специальных адресов IPV4?

    Проверьте, доступен ли порт на удаленной системе (без telnet)

    Как определить, есть ли у вас интернет-соединение в R

    Генерировать ключ аутентификации для ssh

    Как использовать GhostScript для Windows для восстановления поврежденных файлов PDF

    Bash не работает после обновления Windows 10

    Доставка сообщения JMS до совершения транзакции

    Вставка / обновление многих из многих структур Entity Framework. Как мне это сделать?

    Создание доступных компонентов пользовательского интерфейса в Delphi

    Давайте будем гением компьютера.