Подтвердить что ты не робот

Вопросительные знаки в регулярных выражениях

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

Благодарю вас

4b9b3361

Ответ 1

Ключевая разница между ? и ?? связана с их лени. ?? ленив, ? нет.

Предположим, вы хотите найти слово "автомобиль" в тексте, но вы не хотите ограничиваться только единственным "автомобилем"; вы также хотите совместить с множественными "машинами".

Здесь примерное предложение:

I own three cars.

Теперь, если бы я хотел совместить слово "автомобиль", и я хотел только получить строку "автомобиль" взамен, я бы использовал ленивый ?? так:

cars??

Это говорит: "Ищите слова" автомобиль "или" автомобили ", и если вы найдете, верните car и ничего больше".

Теперь, если бы я хотел сопоставлять одни и те же слова ( "автомобиль" или "автомобили" ), и я хотел получить весь матч взамен, я бы использовал не-ленивый ? так:

cars?

Это говорит: "Ищите слова" автомобиль "или" автомобили ", и возвращай автомобиль или автомобили, что бы вы ни нашли".

В мире компьютерного программирования ленивый обычно означает "оценивать только столько, сколько необходимо". Таким образом, ленивый ?? возвращает столько, сколько необходимо для соответствия; поскольку "s" в "автомобилях" не является обязательным, не возвращайте его. С другой стороны, ленивые (иногда называемые жадные) операции оценивают как можно больше, поэтому ? возвращает все совпадения, включая необязательные "s".

Лично я обнаруживаю, что использую ? как способ сделать другие операторы регулярных выражений ленивыми (например, операторами * и +) чаще, чем я использую его для простоты символа, но YMMV.

См. в коде

Здесь выше реализовано в Clojure в качестве примера:

(re-find #"cars??" "I own three cars.")
;=> "car"

(re-find #"cars?" "I own three cars.")
;=> "cars"

Элемент re-find - это функция, которая принимает свой первый аргумент как регулярное выражение #"cars??" и возвращает первое совпадение, которое оно находит во втором аргументе "I own three cars."

Ответ 2

Это отличный вопрос, и мне потребовалось некоторое время, чтобы понять, что такое ленивый квантор ??.

? - Необязательный (жадный) квантификатор

Полезность ? достаточно проста для понимания. Если вы хотите найти как http, так и https, вы можете использовать такой шаблон:

https?

Этот шаблон будет соответствовать обоим входам, поскольку он делает s опциональным.

?? - Необязательный (ленивый) квантификатор

?? более тонкий. Обычно это делает то же самое ?. Он не меняет истинный/ложный результат, когда вы спрашиваете: "Этот вход соответствует этому регулярному выражению?" Вместо этого это имеет отношение к вопросу: "Какая часть этого ввода соответствует этому регулярному выражению и какие части принадлежат к каким группам?" Если входной сигнал может удовлетворять шаблону более чем одним способом, то механизм решит, как сгруппировать его на основе ? vs. ?? (или * vs. *?, или + vs. +?).

Скажите, что у вас есть набор входов, которые вы хотите проверить и проанализировать. Вот пример (по общему признанию, глупый):

Input:       
http123
https456
httpsomething

Expected result:
Pass/Fail  Group 1   Group 2
Pass       http      123
Pass       https     456
Pass       http      something

Вы пробуете первое, что приходит на ум, это this:

^(http)([a-z\d]+)$
Pass/Fail  Group 1   Group 2    Grouped correctly?
Pass       http      123        Yes
Pass       http      s456       No
Pass       http      something  Yes

Все они проходят, но вы не можете использовать второй набор результатов, потому что вам нужно только 456 в группе 2.

Хорошо, пусть повторите попытку. Пусть говорят, что группа 2 может быть буквами или цифрами, но не обе:

(https?)([a-z]+|\d+)
Pass/Fail  Group 1   Group 2   Grouped correctly?
Pass       http      123       Yes
Pass       https     456       Yes
Pass       https     omething  No

Теперь второй ввод прекрасен, но третий из них сгруппирован неправильно, потому что ? по умолчанию жадность (+ тоже, но сначала появился ?). При принятии решения о том, является ли s частью https? или [a-z]+|\d+, если результат является проходом в любом случае, механизм регулярных выражений всегда будет выбирать один из них слева. Таким образом, группа 2 теряет s, потому что Группа 1 втянула ее.

Чтобы исправить это, вы делаете одно крошечное изменение:

(https??)([a-z]+|\d+)$
Pass/Fail  Group 1   Group 2    Grouped correctly?
Pass       http      123        Yes
Pass       https     456        Yes
Pass       http      something  Yes

По существу, это означает: "Матч https, если вам нужно, но посмотрите, продолжает ли это, когда группа 1 просто http". Двигатель понимает, что s может работать как часть [a-z]+|\d+, поэтому он предпочитает помещать его в группу 2.

Ответ 3

? просто делает предыдущий элемент (символ, класс символов, группа) необязательным:

colou?r

соответствует "цвет" и "цвет"

(swimming )?pool

соответствует "пулу" и "плавательный бассейн"

?? то же самое, но он также ленив, поэтому элемент будет исключен, если это вообще возможно. Как отмечают эти документы,?? на практике редко. Я никогда не использовал его.

Ответ 4

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

Кроме того, что объясняется в других ответах, , в регулярных выражениях еще есть еще 3 вопроса использования знаков вопроса.

  • Отрицательный Lookahead

    Отрицательные образы используются, если вы хотите что-то не сопровождается чем-то другим. Отрицательный lookahead construct - это пара круглых скобок, с открытием скобки, а затем знак вопроса и восклицательный знак. x(?!x2)

    Пример

    • Рассмотрим слово There
    • Теперь по умолчанию RegEx e найдет третью букву e в слове There.

      There
        ^
      
    • Однако, если вы не хотите e, за которым сразу следует r, вы можете использовать RegEx e(?!r). Теперь результатом будет:

      There
          ^
      
  • Положительный Lookahead

    Положительный lookahead работает точно так же. q(?=u) соответствует a q, что сразу следует a u, не делая u часть совпадение. Положительный конструктор lookahead представляет собой пару круглых скобок, с открывающейся скобкой, за которой следует знак вопроса и равно знаку.

    Пример

    • Рассмотрим слово getting
    • Теперь по умолчанию RegEx t найдет третью букву t в слове getting.

      getting
        ^
      
    • Однако, если вы хотите t, за которым сразу следует i, вы можете использовать RegEx t(?=i). Теперь результатом будет:

      getting
         ^
      
  • Не-захват групп

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

    Если вам не нужна группа, чтобы зафиксировать ее соответствие, вы можете оптимизировать это регулярное выражение в

    (?:Value)
    

См. также this и this.