Страницы

Поиск по вопросам

среда, 27 февраля 2019 г.

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

Добрый вечер. Понимаю, что вопрос очень глупый, но голова уже не варит. Да, начинается время зачетов :) Для N-ной лабы по матстату нужно посчитать количество вхождений подстроки в строку. Банальщина. Чтобы эту банальщину хоть как-то приукрасить, пишем extension method для string: public static int P(this string baseStr, string inputStr) { return new Regex(inputStr).Matches(baseStr).Count; } Для справки - в задании строка из N 0 и 1, первым этапом надо посчитать вероятности появления пар в строке. Собственно, мой глупый вопрос: почему описанный метод, вызванный от строки "1111" возвращает 2? Ну не могут же регулярки последовательно считать... UPD: пример вызова метода: string data = "1111"; Console.WriteLine(data.P("11")); //2


Ответ

Всё верно: в строке 1111 всего два вхождения подстроки 11. Регулярные выражения анализируют текст слева направо. При совпадении внутренний "курсор" (индекс) устанавливается на его начальную позицию. Следущее совпадение система начинает искать с позиции, находящейся сразу после текущего совпадения. Таким образом, перекрёстные совпадения невозможны при использовании обычных шаблонов.
Как верно заметил ReinRaus, необходимо воспользоваться механизмом опережающей проверки, т.е. конструкцией (?=...), которая используется для проверки того, что следует после текущей позиции в строке. Несмотря на то, что такие блоки не "поглощают" текст при совпадении (т.е. при нахождении подстроки индекс остаётся на прежнем месте во входной строке), внутри них возможно использование захватывающих подмасок типа (...)
Тут мы подходим к решению проблемы:
string data = "1111"; string sub = "11"; Console.WriteLine(data.P(string.Format("(?=({0}))", Regex.Escape(sub)));
Здесь пример использования данного подхода

Комментариев нет:

Отправить комментарий