чего то меня вдохновил этот вопрос, хочу поделиться личными наблюдениями об подмасках(подгрупах, групах, подшаблонах, подпатернах и другие синонимы)
(patern) или (?:patern) - это подмаски.
для движка PCRE это что то типа функция или подпрограмма.
также как и в php функции имеют входящие и исходящие агрументы.
(patern) - эту конструкцию в php можно было бы выразить наподобии следущего
$patern_1 = function($patern, $text){preg_match($patern, $text, $result); return $result[0];}
$text - это данные которые регулярка еще не обработала.
$patern - это сама регулярка которая написана в подмаске.
$patern_1 - это переменная в которую сохраняеться результат, мы позже можем к ней обращаться например так \1 или по новому \g{1}
Конструкция (?:patern) это аналогично предыдущему варианту(patern) только без сохранения результата в переменную.
Теперь интересный нюанс, подмаски могут возращать всего три типа переменных:
1) String - текст который нашла регулярка, должна иметь хотябы 1 символ
2) Null - нулевая длинна совпадения, это string но без символов (как в php пустой стринг $patern_1 = '')
3) False - регулярка ничего не нашла, а Null по условию не считаеться удовлетворительной
Примеры:
preg_match('/^(abc)/', 'abc') - тут в первой группе(\1) будет текст String abc, preg_match вернет true
preg_match('/^(abc)/', 'abv') - тут в первой группе(\1) будет текст False, preg_match вернет false
preg_match('/^(abc)?/', 'abv') - тут в первой группе(\1) будет текст Null, preg_match вернет true
False заставляет регулярку двигаться назад, тоесть искать альтернативные пути, что бы обойти false.
Null позволяет регулярке двигаться вперед как будьто и не было никаких препятствий на пути
String позволяет регулярке двигаться вперед сдвинув курсор за найденным текстом.
Теперь посмотрим на условную подмаску (?(1)есть|нету)
(1) - это заглядывание на переменную $patern_1.
аналогия с php if(empty($patern_1))
конструкция if может вернуть только булевое значение true или false.
- если переменная $patern_1 не существует то результат будет False
- если на входе будет string хотябы с 1 символом то результат true
- если на входе будет Null то результат будет False
- если на входе будет False то на выходе тоже будет False, хотя последние в условной подмаске не может быть, так как false не далбы регулярке дойти до условной подмаски.
Мой личный вывод:
В регулярах подмаски это аналог подпрограмм, с входящими и исходящими аргументами.