Как работает? сделайте квантификатор ленивым в регулярном выражении
Я в последнее время изучал регулярные выражения и понял, что ?
оператор делает *
,+
, или же ?
ленивый. Мой вопрос, как это сделать? Это оно *?
например, специальный оператор, или делает ?
оказывать влияние на *
? Другими словами, распознает ли регулярное выражение *?
как один оператор сам по себе, или 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'
Дополнение "?" операторы + и * делают их "ленивыми" - т.е. они будут соответствовать абсолютному минимуму, необходимому для того, чтобы выражение было истинным. Принимая во внимание, что по умолчанию операторы * и + являются "жадными" и пытаются найти соответствие, которое МОЖНО КАК ВОЗМОЖНО, чтобы выражение было истинным.
Помните, + означает "один или несколько", поэтому минимум будет "один, если возможно, больше, если это абсолютно необходимо", тогда как максимум будет "все, если возможно, один, если это абсолютно необходимо".
И * означает "ноль или более", поэтому минимум будет "ничего, если возможно, больше, если это абсолютно необходимо", тогда как максимум будет "все, если это возможно, ноль, если это абсолютно необходимо".
Я думаю, это очень сильно зависит от реализации. Но так как каждый квантификатор, который я знаю, может быть изменен с ?
было бы разумно реализовать это таким образом.