Что означает конструкция ‘??’ (два вопросительных знака) в регулярных выражениях?

«Что означает конструкция ‘??’ (два вопросительных знака) в регулярных выражениях?» — вопрос из категории Основы программирования, который задают на 10% собеседований QA Тестировщик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Конструкция ?? в регулярных выражениях — это ленивый (нежадный) квантификатор, означающий "ноль или одно вхождение". Он заставляет предшествующий элемент (символ, группу, класс) совпадать минимально возможное количество раз (в данном случае — 0 раз, если это позволяет общему шаблону совпасть).

Сравнение с жадным (?) и ленивым (??) режимами:

  • a? (жадный): Сопоставит максимально возможное количество 'a' (0 или 1), но не меньше.
  • a?? (ленивый): Сопоставит минимально возможное количество 'a' (0 или 1), предпочитая 0.

Практический пример:

Рассмотрим строку 'aaab' и шаблон 'a??b'.

  1. Движок Regex начинает с позиции 0.
  2. Часть a?? старается совпасть 0 раз (ленивый режим).
  3. Далее движок пытается совпасть с 'b', но на позиции 0 у нас 'a' — совпадения нет.
  4. Движок откатывается (backtrack) и заставляет a?? совпасть 1 раз.
  5. Теперь на позиции 1 движок снова пытается совпасть с 'b' (символ 'a') — не удаётся.
  6. Процесс повторяется, пока a?? не совпадёт с тремя символами 'a', и только тогда 'b' на четвёртой позиции найдёт совпадение.

Итоговое совпадение для 'a??b' и строки 'aaab''aaab'. Хотя ленивый квантификатор "не хочет" брать символы, общее совпадение шаблона оказывается приоритетнее.

Более показательный пример с захватом:

# Текст: <div>text</div>
<.*?>   # Ленивый квантификатор: совпадёт с '<div>' (первое '>')
<.*>    # Жадный квантификатор: совпадёт со всей строкой '<div>text</div>'

Использование с группами: (?:a)?? — необязательная незахватывающая группа, которую движок постарается проигнорировать в первую очередь.