Ответ
Конструкция ?? в регулярных выражениях — это ленивый (нежадный) квантификатор, означающий "ноль или одно вхождение". Он заставляет предшествующий элемент (символ, группу, класс) совпадать минимально возможное количество раз (в данном случае — 0 раз, если это позволяет общему шаблону совпасть).
Сравнение с жадным (?) и ленивым (??) режимами:
a?(жадный): Сопоставит максимально возможное количество'a'(0 или 1), но не меньше.a??(ленивый): Сопоставит минимально возможное количество'a'(0 или 1), предпочитая 0.
Практический пример:
Рассмотрим строку 'aaab' и шаблон 'a??b'.
- Движок Regex начинает с позиции 0.
- Часть
a??старается совпасть 0 раз (ленивый режим). - Далее движок пытается совпасть с
'b', но на позиции 0 у нас'a'— совпадения нет. - Движок откатывается (backtrack) и заставляет
a??совпасть 1 раз. - Теперь на позиции 1 движок снова пытается совпасть с
'b'(символ'a') — не удаётся. - Процесс повторяется, пока
a??не совпадёт с тремя символами'a', и только тогда'b'на четвёртой позиции найдёт совпадение.
Итоговое совпадение для 'a??b' и строки 'aaab' — 'aaab'. Хотя ленивый квантификатор "не хочет" брать символы, общее совпадение шаблона оказывается приоритетнее.
Более показательный пример с захватом:
# Текст: <div>text</div>
<.*?> # Ленивый квантификатор: совпадёт с '<div>' (первое '>')
<.*> # Жадный квантификатор: совпадёт со всей строкой '<div>text</div>'
Использование с группами: (?:a)?? — необязательная незахватывающая группа, которую движок постарается проигнорировать в первую очередь.