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

Income: ## . ## , Bank percent: ## , taxes ## energy ## .

Заметим, что метод Replace имеет 10 переопределенных версий, которые позволяют более гибко управлять алгоритмом поиска и замены.

Поиск ссылок

Рассмотрим пример, демонстрирующий, как с помощью регулярных выражений получить список ссылок, которые имеются в каком-либо документе HTML. Предположим, мы имеем htm-файл со списком различных типов графических файлов. Этот документ содержит также полезные для нас ссылки, которые мы хотим выделить и вывести на экран, или сохранить в отдельном текстовом файле.

Документ содержит десятки ссылок, которые надо найти и выделить с помощью инструментария, предоставляемого технологией регулярных выражений. Ссылкой обычно считают значение атрибута href тега <a>. Рассмотрим все возможные варианты ссылок.

<!-- Определение якоря (места ссылки в документе) -->

<a name="myAnchor">

<!-- Ссылка на якорь myAnchor -->

<a href="#myAnchor">Anchor</a>

<!-- Ссылка на файл в папке, где расположен активный документ -->

<a href="home.htm">home.htm</a>

<!-- Ссылка на сервер, точнее на default-страницу сервера -->

<a href="http://www.microsoft.com">Microsoft home page.</a>

<!-- Ссылка на файл, открываемый в окне, указанном в target -->

<a target="viewer" href="sample.htm">Open in window</a>

<!-- Ссылка на default-страницу сервера с помощью картинки -->

<a href="http://www.microsoft.com"><img src="images/bullet.gif">link</a>

<!-- Ссылка на JScript function -->

<a href="javascript:window.open()">link</a>

Анализируя эти варианты, можно придти к выводу, что значение атрибута href всегда заключено в двойные кавычки. Однако, современные браузеры допускают и отсутствие кавычек в подобных конструкциях. Мы должны создать шаблон, который выявит значение атрибута в обоих случаях.

Итак, мы собираемся искать все вхождения слова href, но нас будет интересовать только значение этого атрибута, то есть текст, который следует за ним (после знака присвоения и до границы, которая задана либо пробелом, либо символом ", либо символом >. Сама граница нас не интересует. В таких случаях (когда что-то немногочисленное не нужно) удобнее пользоваться инверсией. Сначала мы описываем множество ненужных символов, затем получаем множество интересующих путем инверсии выражения, то есть записываем дополнение множества ненужных символов и используем его как группу регулярного выражения при поиске совпадений с шаблоном. В нашем случае целесообразно определить такую именованную группу:

(?<1>[^\\s>]+)

Определена группа с именем 1. Именованные группы можно идентифицировать не только символами, но и цифрами (меньше усилий). Она генерирует частичное совпадение (Capture), когда испытуемая строка содержит любые символы, кроме whitespace и символа >. Роль повторителя + очевидна.

Эта группа — только часть шаблона. Ее можно использовать для описания одного из вариантов тела атрибута href. Важно то, что задана именованная группа. Это позволит впоследствии вытащить уже выловленное значение атрибута href путем обращения к коллекции групп, например так: match.Groups[1].

Другой вариант тела атрибута href можно вставить в регулярное выражение в виде альтернативы (с помощью операции ИЛИ). Альтернативный вид группы номер 1 запишем таким образом:

(?<1>[^\"]*)

Эта группа ловит все символы, кроме символа ". Ему должен предшествовать backslash для того, чтобы рассматривать его как символ, а не как мета-символ (граница строкового литерала). Теперь соединим две альтернативы, дополнив вторую обязательными символами кавычек.

(?<1>[^\\s>]+)|\"(?<1>[^\"]*)\"

Эту часть шаблона можно прочесть так. Группа один — это:

¨  Либо последовательность из любых символов, кроме whitespace и символа закрытия тега >.

¨  Либо последовательность из открывающих литерал кавычек, любых символов, кроме кавычек, и закрывающих кавычек,