Как работает? сделайте квантификатор ленивым в регулярном выражении

Я в последнее время изучал регулярные выражения и понял, что ? оператор делает *,+, или же ? ленивый. Мой вопрос, как это сделать? Это оно *? например, специальный оператор, или делает ? оказывать влияние на *? Другими словами, распознает ли регулярное выражение *? как один оператор сам по себе, или Regex распознает *? как два отдельных оператора * а также ?? Если это так, что *? распознается как два отдельных оператора, как ? влиять на * сделать это ленивым. Если ? означает, что * не является обязательным, не означает ли это, что * не должен существовать вообще. Если так, то в заявлении .*? не будет ли регулярное выражение сопоставлять отдельные буквы и целую строку вместо более короткой? Пожалуйста, объясните, я отчаянно хочу понять. Большое спасибо.

4 ответа

Решение

Я думаю, что небольшая история облегчит понимание. Когда Ларри Уолл хотел расширить синтаксис регулярных выражений для поддержки новых функций, его возможности были сильно ограничены. Он не мог просто постановить (например), что % теперь метасимвол, который поддерживает новую функцию "XYZ". Это сломало бы миллионы существующих регулярных выражений, которые случайно использовали % соответствовать буквальному знаку процента.

Что он мог сделать, так это взять уже определенный метасимвол и использовать его таким образом, чтобы его первоначальная функция не имела смысла. Например, любое регулярное выражение, содержащее два квантификатора в строке, будет недопустимым, поэтому можно с уверенностью сказать, ? после того, как другой квантификатор теперь превращает его в неохотный квантификатор (гораздо более подходящее название, чем "ленивый" IMO; тоже не слишком жадный). Так что ответ на ваш вопрос таков: ? не изменяет *, *? это единое целое: неохотный квантификатор. То же самое относится и к + в собственнических квантификаторах (*+, {0,2}+ так далее.).

Аналогичный процесс произошел с групповым синтаксисом. Никогда не имело бы смысла иметь квантификатор после неэкранированной открывающей скобки, поэтому можно с уверенностью сказать, (? теперь отмечает начало специальной групповой конструкции. Но один вопросительный знак будет поддерживать только одну новую функцию, поэтому ? За самим собой должен следовать хотя бы еще один символ, чтобы указать, к какой группе это относится ((?:...), (?<!...), так далее.). Опять же, (?: является одним объектом: начальный разделитель не захватывающей группы.

Я не знаю, почему он использовал вопросительный знак оба раза. Я знаю, что правила Perl 6 (переписывание регулярных выражений Perl 5 снизу вверх) покончили со всем этим дерьмом и используют бесконечно более разумный синтаксис.

? может означать много разных вещей в разных контекстах.

  • После обычного токена регулярного выражения (символ, сокращение, класс символа, группа...) это означает "Сопоставить предыдущий элемент 0-1 раз".
  • После квантификатора, как ?, *, +, {n,m}, он принимает другое значение: "Сделайте предыдущий квантификатор ленивым вместо жадного (если это значение по умолчанию; это можно изменить, хотя - например, в PHP, /U модификатор делает все квантификаторы ленивыми по умолчанию, поэтому дополнительный ? делает их жадными).
  • Сразу после открывающей скобки он отмечает начало специальной конструкции, как, например,

    а) (?s): модификаторы режима ("включить режим dotall")
    б) (?:...): сделать группу без захвата
    с) (?=...) или же (?!...): предположение
    г) (?<=...) или же (?<!...): lookhehind утверждение
    е) (?>...): атомная группа
    е) (?<foo>...): именованная группа захвата
    г) (?#comment): встроенные комментарии, игнорируются движком регулярных выражений
    час) (?(?=if)then|else): условия

и другие. Не все конструкции доступны во всех вкусах регулярных выражений.

  • Внутри класса персонажа ([?]), это просто соответствует дословно ?,

Представьте, что у вас есть следующий текст:

BAAAAAAAAD

Вернутся следующие регулярные выражения:

/B(A+)/ => 'BAAAAAAAA'
/B(A+?)/ => 'BA'
/B(A*)/ => 'BAAAAAAAA'
/B(A*?)/ => 'B'

Дополнение "?" операторы + и * делают их "ленивыми" - т.е. они будут соответствовать абсолютному минимуму, необходимому для того, чтобы выражение было истинным. Принимая во внимание, что по умолчанию операторы * и + являются "жадными" и пытаются найти соответствие, которое МОЖНО КАК ВОЗМОЖНО, чтобы выражение было истинным.

Помните, + означает "один или несколько", поэтому минимум будет "один, если возможно, больше, если это абсолютно необходимо", тогда как максимум будет "все, если возможно, один, если это абсолютно необходимо".

И * означает "ноль или более", поэтому минимум будет "ничего, если возможно, больше, если это абсолютно необходимо", тогда как максимум будет "все, если это возможно, ноль, если это абсолютно необходимо".

Я думаю, это очень сильно зависит от реализации. Но так как каждый квантификатор, который я знаю, может быть изменен с ? было бы разумно реализовать это таким образом.

Другие вопросы по тегам