Правильные (Regular) выражения и класс Regex. Операторы над компонентами регулярных выражений, страница 5

Capture: 'bit', Pos = 3

3. Match: 'bit',  Pos = 6, 1 Groups

0. Group: 'bit', 1 Captures

Capture: 'bit', Pos = 6

Найдено 3 совпадения и все они принадлежат нулевой группе. Напомним, что это вся строка шаблона регулярного выражения ("bit"). В этой группе имеется одна подстрока (Capture), совпавшая с шаблоном 'bit'. Результат не изменится, если мы слегка усложним шаблон и добавим повторитель: pattern = "bit+";. Причина в том, что он действует только на одну букву t.

Однако, картина заметно изменится, если мы введем группу (bit) и применим к ней повторитель +. Замените шаблон на "(bit)+" и запустите тестовую программу.

Еще больше усложним шаблон: pattern = "((b(i))t)+";. Сколько групп здесь определено? Метод Match будет по очереди искать вхождения всех групп. Так как использован повторитель +, то догадаться, что выведет программа не просто. Запустите и объясните результат.

В качестве упражнения просчитайте, что выведет наш кодовый фрагмент, если:

text = "oz";

pattern = "z*";

Шаблон "z*" имеет некий вербальный эквивалент. Мы просим найти нуль или более вхождений символа z. Сколько совпадений обнаружит наш фрагмент?

Здесь вспоминается ситуация, довольно часто повторявшаяся в дни, когда.... Когда одному уважаемому профессору нашего Политеха задавали "странный" вопрос, то он обычно не критиковал вопрос, а давал на него столь же "странный" ответ. Если спрашивающий высказывал удивление по поводу услышанного, то в ответ получал поговорку: "Каков вопрос, таков ответ".

Кроме этого вспоминается, что каждое множество содержит лишь одно пустое подмножество. Документация Microsoft по этому поводу (см. страницы: Quantifiers and Empty Matches и Next Match After an Empty Match) не забывает похвалить себя. Рассуждения таковы. Шаблон "z*" эквивалентен "z{0,¥}", но алгоритм никогда не повторит пустое соответствие (an empty match), если минимальное число соответствий n из {n, m} уже достигнуто. Это правило предотвращает появление бесконечных циклов (prevents quantifiers from entering infinite loops on empty matches). Здесь все правда (бесконечных циклов не будет), но просчитайте или проверьте с помощью нашего фрагмента, что будет, если задать:

text = "Love me or hate me. (Microsoft)";

pattern = "z*";

Итак, будем задавать осмысленные вопросы. Вычислите, что выведет метод Test, если:

text = "gooogle";

pattern = "o{1,3}";

Ответ, который вы получили, трактуют как свойство и называют его жадностью алгоритма ('greedy' algorithm) поиска соответствий. Точнее будет сказать, что жадность проявляют все повторители, они хотят обнаружить максимальное число вхождений своего pattern'а. Здесь я прошу вас возвратиться к таблице повторителей (Quantifiers) и убедиться в том, что она содержит 6 строк, соответствующих 6 повторителям (*, +, ?, {n}, {n,}, {n,m}). На самом деле таблица должна содержать 12 строк. Я не привел еще 6 строк, которые соответствуют шести "ленивым" соратникам ("lazy" counterparts) присутствующим в таблице повторителей. Ленивые образуются из жадных путем добавления справа символа ?. Испытайте ленивый вариант предыдущего поиска.

text = "gooogle";

pattern = "o{1,3}?";

Ленивость повторителя состоит в том, что поиск прекращается при нахождении минимального совпадения. Поэтому, сканируя строку, алгоритм вместо одного "большого" совпадения найдет три маленьких. Следующий вопрос: Что выведет метод, если:  text = "goooogle"; pattern = "o{1,3}";? Ленивый вариант ("o{1,3}?"), соответствующий рассмотренному, должен быть вам очевиден.

Что будет выведено, если text="gooooooogle";? Следующий пример демонстрирует, как пользоваться ссылкой на группу.

text = "Tool is too cool and irregular";

pattern = @"(.)\1";

Последовательность \1 является ссылкой на группу (.). В итоге, мы просим найти все вхождения двух одинаковых символов. Каков же будет результат?