Введение
Регулярные выражения - это мощная технология, предназначенная для работы
со строками. Она была создана в шестидесятые годы, задолго до появления
персональных компьютеров. Широко применяется в скриптовых языках
программирования - Perl, Jscript, VBScript.
Вы уже знаете, что недавно Microsoft выпустила в свет платформу .NET
Framework. В неё были встроены классы для работы с регулярными
выражениями. Ниже будет кратко описаны возможности регулярных выражений
и принципы работы с ними на языке Visual Basic .NET.
Что такое регулярные выражения
Если Вы уже знакомы с регулярными выражениями, то можете смело
пропустить этот раздел.
С помощью регулярных выражений вы можете производить поиск, замену
подстрок, используя шаблоны. Они состоят из обычных символов и так
называемых метасимволов (metacharacters) - управляющих символов. Список
метасимволов достаточно обширен. Ниже приведены наиболее часто
используемые символы.
Символ |
Описание |
* |
Соответствует выражению, находящемуся до знака "*", взятому
ноль или более раз. Например, шаблон "[0-9]*" определяет строку,
содержащую ноль или более цифр. |
\ |
Предназначен для определения символа, являющегося
метасимволом. Например, шаблон "." соответствует любому символу,
а шаблон "\." будет соответствовать точке. |
^ |
Определяет начало входной строки. |
$ |
Определяет конец входной строки. |
+ |
Соответствует выражению, находящемуся до знака "+", взятому
один или более раз. Например, шаблон "[0-9]+" определяет строку,
содержащую одну или более цифр. |
. |
Определяет любой символ кроме символа перевода строки. |
| |
Разделяет два выражения. Например, шаблону "a|b" будут
соответствовать строки "a" и "b". |
[a-z] |
Определяет диапазон символов. Например, шаблон "[0-9]"
определяет цифру. |
[^...] |
Определяет любой символ, не соответствующий заданному
набору. Например, шаблон "[^0-9]" определяет любой символ, кроме
цифры. |
\w |
Слово. То же, что и [a-zA-Z_0-9]. |
\W |
Все, кроме слов. То же, что и [^a-zA-Z_0-9]. |
\s |
Любое пустое место. То же, что и [ \f\n\r\t\v]. |
\S |
Любое непустое место. То же, что и [^ \f\n\r\t\v]. |
\d |
Десятичная цифра. То же, что и [0-9]. |
\D |
Не цифра. То же, что и [^0-9]. |
Другие метасимволы вы можете найти в MSDN . Ниже приведён простой
пример регулярного выражения - шаблон номера телефона.
^(\(\d+\)){0,1}\d{3}-\d{2}-\d{2}$
Это выражение может показаться сложным, хотя на самом деле всё
просто. Начинаем разбор полётов…
- ^ - Этот символ указывает, что здесь начинается искомая строка.
- (- Код города располагается внутри скобок.
- \( - Открывающая скобка.
- \d+ - После скобки должен располагаться код города - одна или
несколько цифр.
- \) - Закрывающая скобка.
- ) - Закрывающая скобка - метасимвол, указывающий, что здесь
заканчивается группируемое выражение (в данном случае, код города).
- {0,1} - Этот метасимвол указывает, что выражение в скобках (код
города) может повторяться от нуля до одного раза, то есть код города
можно не указывать.
- \d{3}-\d{2}-\d{2} - Три группы цифр - одна группа по три и две
по две цифры. Цифры разделены дефисами.
- $ - Этот знак показывает, что здесь заканчивается подстрока.
Класс RegEx
Для работы с регулярными выражениями в VB .NET используется класс RegEx,
находящийся в пространстве имён System.Text.RegularExpressions. С
помощью этого класса вы можете производить следующие действия:
- Поиск подстрок по шаблону
- Замена подстрок по шаблону
- Сравнение строки с шаблоном
- Разделение строки на подстроки с использованием шаблонов.
Ниже эти действия будут рассмотрены подробнее.
Для произведения действий с регулярными выражениями необходимо
создать экземпляр класса RegEx. Для этого используется стандартный
конструктор New. Он перегружен и имеет две комбинации параметров. Вы
можете задать только шаблон (переменная типа String), который будет
использоваться в дальнейшем, либо шаблон и параметры объекта. Параметры
задаются константами из перечисления RegExOptions. Ниже приведены
константы и их описания.
Константа |
Описание |
Compiled |
Указывает, что регулярное выражение будет скомпилировано в
сборку. Подробнее о компилированных регулярных выражениях
читайте ниже. |
ECMAScript |
Устанавливает ECMAScript-совместимость выражения. Может
использоваться совместно с константами IgnoreCase, Multiline и
Compiled. При использовании ECMAScript с другими константами
будет инициировано исключение. |
IgnoreCase |
Определяет, что при проведении операций с выражениями,
регистр не имеет значения. |
IgnorePatternWhitespace |
Устраняет пробелы из шаблонов и позволяет использовать
комментарии, отмеченные знаком "#". |
Multiline |
Если этот флаг установлен, то метасимволы "^" и "$" отмечают
начало и конец каждой строки (строки разделены знаком перевода
строки), а не начало и конец всего выражения. |
None |
Указывает, что не установлена ни одна опция. |
RightToLeft |
Устанавливает, что поиск будет производиться с права на
лево, а не наоборот. |
SingleLine |
Указывает, что операции будут производиться в однострочном
режиме. Эта константа изменяет значение метасимвола ".". Он
определяет любой символ, включая символ перевода строки. |
Поиск подстрок, соответствующих шаблону производится с помощью
перегруженного метода Matches. Он может принимать 4 комбинации
параметров. Первый параметр - строка, в которой будет производиться
поиск. В качестве второго параметра можно установить позицию, с которой
будет начат поиск. Также вторым параметром можно указать шаблон (если он
не совпадает с шаблоном, указанным в конструкторе при создании объекта).
И последняя комбинация параметров - строка для поиска, шаблон и
параметры поиска, заданные комбинацией констант перечисления
RegExOptions (см. таблицу 1).
Метод возвращает объект MatchCollection. Это коллекция, которая
содержит объекты Match. Получить объект Match можно с помощью
индексированного свойства Item коллекции. Нумерация элементов начинается
с нуля. Чтобы получить найденную подстроку, следует использовать
свойство Value объекта Macth.
Ниже приведён небольшой пример поиска тэгов в HTML коде.
Dim regexp As New Regex("<(.*?)>")
Dim html As String
Dim i As Integer
Dim m As MatchCollection
html = "<p>Это <a href='http://vbnet.ru'>пример</a> <b>поиска</b></p>"
m = regexp.Matches(html)
For i = 0 To m.Count - 1
MsgBox(m.Item(i).Value)
Next
Замена
Другое часто используемое действие, производимая с помощью класса
RegEx - замена подстрок с использованием шаблонов. Для замены
используется метод Replace. Он, как и метод Matches, перегружен. Replace
может принимать 10 комбинаций параметров. Я не буду перечислять здесь
все - вы можете найти их в MSDN или в Object Browser. Метод может
принимать комбинации из следующих параметров:
- input - Исходная строка.
- replacement - Строка, на которую будут заменены найденные
подстроки.
- count - Максимальное количество замен.
- startat - Позиция в строке input, с которой будет производиться
замена.
- pattern - Заменяемый шаблон.
- options - Опции. Может принимать константы из перечисления
RegExOptions.
- evaluator - Объект MatchEvaluator.
Метод возвращает переменную типа String - строка, в которой были
произведены замены.
Dim regexp As New System.Text.RegularExpressions.Regex("<(.*?)>")
Dim InputString As String
InputString = "p>Это <a href='http://vbnet.ru'>пример</a> <b>pfvtys</b></p>"
txtText.Text = regexp.Replace(txtText.Text, "[вырезано]", RegexOptions.Multiline)
Сравнение
Сравнение строки с шаблоном - самая простая операция, которую можно
произвести с помощью класса RegEx. Сравнение осуществляется методом
IsMatch. Он перегружен и может принимать такие же параметры, как и метод
Matches. Возвращаемое значение имеет тип Boolean. Метод возвращает True,
если тестируемая строка совпадает с шаблоном и False в противном случае.
Ниже приведён пример сравнения строки с шаблоном.
Dim regexp As New System.Text.RegularExpressions.RegEx ("[0-9]+")
Dim str As String
str = "1234567890"
MsgBox (regexp.IsMatch(str).ToString)
str = "abc"
MsgBox (regexp.IsMatch(str).ToString)
Разделение строки
Разделение строки используется реже остальных операций. Разделение
строки с использованием регулярных выражений очень схоже с обычным
разделением строки функцией Split. Но если в Split в качестве
разделителя использовалась строка, то здесь разделителем является
регулярное выражение.
Для разделения строки используется перегруженный метод Split класса
RegEx. Он может принимать такие же комбинации параметров, как и методы
Matches и IsMatch. Split возвращает массив типа String, который содержит
строки, полученные из исходной строки. Массив индексируется с нуля.
Приведу небольшой пример. Допустим, вам нужно разбить строку по
нескольким разделителям (скажем, "-", "." и ","). Можно использовать для
этого функцию Split, но при этом будет много возни с массивами, код
будет сильно загромождён и снизится быстродействие. А теперь посмотрим,
как легко эта операция будет произведена с использованием регулярных
выражений. Разделителем будет являться следующее выражение: "[-\.,]".
Следующий код разбивает строку на подстроки с использованием этого
шаблона.
Dim regexp As New Regex("[-\.,]")
Dim i As Integer
Dim s() As String
Dim str As String
str = "раз-два,три.четыре,пять"
s = regexp.Split(str)
For i = 0 To s.GetUpperBound(0)
Console.WriteLine(s(i))
Next
Компилированные регулярные выражения
По умолчанию RegEx компилирует регулярные выражения в последовательность
внутренних байт-кодов регулярных выражений (это высокоуровневый код).
При выполнении регулярных выражений происходит интерпретация байт-кода.
Если при создании объекта RegEx в конструкторе New была установлена
константа Compiled, то RegEx будет скомпилирован в MSIL (Microsoft
intermediate language). Это позволит JIT-компилятору преобразовать
выражение в машинный код, что значительно повышает производительность.
Однако в компилированных выражениях есть и плохая сторона - их нельзя
выгрузить из памяти. Компилированные регулярные выражения выгружаются
только при завершении работы всего приложения. RegEx остается в памяти,
даже когда сам объект освобождён и уничтожен сборщиком мусора.
Поэтому, следует задуматься над тем, стоит ли устанавливать флаг
Compiled. Если вы постоянно используете несколько регулярных выражений,
то лучше будет их скомпилировать.
Заключение
Регулярные выражения - мощная технология для работы с текстом. Радует
то, что разработчики Microsoft всё-таки встроили поддержку этой
технологии в .NET Framework. Возможно, они сделали это потому что .NET
Framework используется в Web-приложениях (ASP .NET), где регулярные
выражения больше всего необходимы.