Жанр: Учеба
Си шарп: создание приложений для windows
... качестве параметра.
При этом результат вернется в виде массива строк. Давайте рассмотрим
работу метода SplitQ на примере:
using System;
using System.Text;
namespace C_Sharp_Examples
{
public class StringTester
{
static void Main( )
{
// строка для анализа
string si = "Один,Два,Три, Строка для разбора";
// задаем разделительные символы для анализа
const char cSpace = ' ';
const char cComma = ',';
// создаем массив разделительных символов
Работа со строками 227
// и инициализируем его двумя элементами
char[] delimiters = new char(] ( cSpace, cComma };
string output = "";
int ctr = 1;
// выделяем подстроки на основе разделителей
// и сохраняем результат
foreach (string substring in si.Split(delimiters))
{
output += ctr++; //номер подстроки
output += ": ";
output += substring; //подстрока
output += "\n"; //переход на новую линию
// вывод результата
Console.WriteLine(output);
Результатом работы программы будет текст:
1: Один
2: Два
3: Три
4:
5: Строка
6: для
7: разбора
Обратите внимание, что строка под номером 4 пуста - это не ошибка.
Ее особенность мы сейчас рассмотрим.
s t r i n g si = "Один,Два,Три, Строка для разбора";
Мы объявили строку si, содержащую шесть слов. В строке используется
два типа разделительных символов. Один из них символ пробела,
другой - символ (,). Между словами "Три" и "Строка" располагаются сразу
два разделительных символа, запятая и пробел. Это очень важно отметить!
Далее в программе объявляются две константы, определяющие разделительные
символы,
const char cSpace = ' ' ;
const char cComma = ', ' ;
Эти константы объединяются в один массив.
char[] delimiters = new char[] ( cSpace, cComma };
Метод Split() может принимать в качестве параметра как один символ,
так и массив разделительных символов. В нашем случае мы используем
в качестве параметра массив разделительных символов из двух элемен228
Раздел I I . Фундаментальные понятия
тов - символа пробела и символа запятой. Следовательно, как только
метод Splitf) обнаружит в исходной строке один из этих символов, то сразу
же поместит в выходной массив последовательность символов от предыдущего
разделителя до текущей позиции.
foreach (string substring in si.Split(delimiters))
Инструкция foreach в данном случае будет применяться ко всем элементам
результирующего массива строк, который вернет функция Split().
Результирующий массив будет состоять из семи элементов, одним из
которых окажется пустая строка. Пустая строка появилась из-за характерной
особенности анализируемой строки. Как я уже отмечал ранее,
между словами "Три" и "Строка" располагаются сразу два разделительных
символа - и запятая, и пробел. Когда Метод Split() дойдет до анализа
символа пробела между "Три" и "Строка", он определит пробел как
разделительный символ. Однако сразу перед ним находится еще один
разделительный символ. Следовательно, между двумя разделительными
символами располагается строка длиной в 0 символов - пустая строка,
которую метод SplitQ и помещает в выходной массив.
КЛАСС StringBuilder
Класс StringBuilder используется для создания и редактирования строк,
обычно строк из динамического набора данных, например из массива
байтовых значений. Наиболее важными членами класса StringBuilder являются:
Capacity - определяет число символов, которые способен хранить и обрабатывать
StringBuilder;
Chars - индексатор класса;
Length - определяет длину объекта StringBuilder;
MaxCapacity - определяет максимальное число символов, которые способен
хранить и обрабатывать StringBuilder;
Appendf) - добавляет объект заданного типа в конец StringBuilder;
AppendFormat() - замещает или устанавливает новый формат StringBuilder;
EnsureCapacity() - гарантирует, что StringBuilder имеет емкость не менее
указанной в параметре;
Insert() - вставляет объект некоторого типа в указанную позицию;
RemoveO - удаляет указанный символ;
Replacef) - замещает все экземпляры указанных символов на новые символы.
Очень важной особенностью класса StringBuilder является то, что при изменении
значений в объекте StringBuilder происходит изменение значений в
исходной строке, а не в ее копии. Давайте рассмотрим пример использования
класса StringBuilder для работы со строками. Возьмем для вывода результатов
в предыдущем примере вместо класса string класс StringBuilder.
Работа со строками 229
using System;
using System.Text;
namespace C_Sharp Examples
public class StringBuilderOutput
{
static void Main( )
{
// строка для анализа
string si = "Один,Два,Три, Строка для разбора";
// задаем разделительные символы для анализа
const char cSpace - ' ';
const char cComma =- ',';
// создаем массив разделительных символов
// и инициализируем его двумя элементами
char[] delimiters ^ new charf] i cSpace, cComma };
StringBuilder output = new StringBuilder();
inn ctr = 1;
// выделяем подстроки на основе разделителей
// и сохраняем результат
foreach (string substring in si.Split(delimiters))
{
// AppendFormac добавляет строку определенного формата
output.AppendFormat("(0}: (1}\n", ctr++, substring];
// вывод результата
Console.WriteLine(output) ;
Как вы могли заметить, изменения произошли лишь в нижней части
кода программы. Работа по разбору строки происходит как обычно, изменился
лишь вывод результатов. Для вывода результатов мы используем
класс StringBuilder.
StringBuilder output - new StringBuilder();
Для объектов класса StringBuilder всегда нужно явно вызывать конструктор,
поскольку этот тип не относится к встроенным типам. При сохранении
результатов обработки строки используется метод AppendFormat().
Данный метод позволяет отформатировать строку необходимым форматом.
Мы передаем в качестве формата строки два значения, разделенные
230 Раздел I I . Фундаментальные понятия
символом двоеточия. Первое значение - это номер подстроки, второе -
сама подстрока.
output.AppendFormat("iO) : (1}\n", ctr++, substring);
При выводе результата нам не потребуется проводить дополнительное
форматирование текста, поскольку мы сразу заносили результат в нужном
формате. Мы просто выводим содержимое StringBuilder в консоль.
Console.WriteLine(output);
Результат работы программы остается таким же, что и ранее:
1: Один
2: Два
3: Три
4:
5: Строка
6: для
7: разбора
РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ
Регулярные выражения - это один из способов поиска подстрок (соответствий)
в строках. Осуществляется с помощью просмотра строки в поисках
некоторого шаблона. Общеизвестным примером могут быть символы
"*" и "?", используемые в командной строке DOS. Первый из них заменяет
ноль или более произвольных символов, второй же - один произвольный
символ. Так, использование шаблона поиска типа "text?.*" найдет файлы
textf.txt, textl.asp и другие аналогичные, но не найдет texttxt или text.htm.
Если в DOS использование регулярных выражений было крайне ограничено,
то в других местах (то есть операционных системах и языках программирования)
они почти достигли уровня высокого искусства.
Применение регулярных выражений дает значительное увеличение
производительности, поскольку библиотеки, интерпретирующие регулярные
выражения, обычно пишутся на низкоуровневых высокопроизводительных
языках (С, C++, Assembler).
Применение регулярных выражений
Обычно с помощью регулярных выражений выполняются три действия:
• проверка наличия соответствующей шаблону подстроки;
• поиск и вьщача пользователю соответствующих шаблону подстрок;
• замена соответствующих шаблону подстрок.
В С# работа с регулярными выражениями выглядит следующим образом:
Regex re = new Regex("образец", "опции");
MatchCollection me = re.Matches("строка для поиска");
iCountMatchs = me.Count;
Работа со строками 231
re - это объект типа Regex. В конструкторе ему передается образец
поиска и опции. Ниже представлена таблица, задающая различные варианты
поиска.
Символ Значение
I Поиск без учета регистра.
m Многострочный режим, позволяющий находить совпадения в начале
или конце строки, а не всего текста.
п Находит только явно именованные или нумерованные группы в
форме (?"name"...).( Значение этого будет объяснено ниже, при обсуждении
роли скобок в регулярных выражениях.)
с Компилирует. Генерирует промежуточный MSIL-код, перед исполнением
превращающийся в машинный код.
s Позволяет интерпретировать конец строки как обыкновенный символразделитель.
Часто это значительно упрощает жизнь.
х Исключает из образца неприкрытые незначащие символы (пробелы,
табуляция и т.д.).
г Ищет справа налево.
Сочетание флагов m и s дает очень удобный режим работы, учитывающий
концы строк и позволяющий пропустить все незначащие символы,
включая символ конца строки.
Основы синтаксиса регулярных выражений
Не стану пытаться написать полный справочник по всем символам,
используемым в шаблонах регулярных выражений, а приведу только
основные метасимволы.
Выражением может быть один символ или последовательность символов,
заключенных в круглые или квадратные скобки. Особенности использования
скобок будут описаны ниже.
Классы символов (Character classes)
Используя квадратные скобки, молено указать группу символов (это
называют классом символов) для поиска. Например, конструкция "б[аи]ржа"
соответствует словам "баржа" и "биржа", т. е. словам, начинающимся
с "б", за которым следуют "а" или "и", и заканчивающимся
на "ржа".
Возможно и обратное, то есть можно указать символы, которые не
должны содержаться в найденной подстроке. Так, '[Л1-6]' находит все символы,
кроме цифр от 1 до 6. Следует упомянуть, что внутри класса символов
'\Ъ' обозначает символ backspace (стирания).
232 Раздел I I . Фундаментальные понятия
Квантификаторы, или умножители (Quantifiers)
Если неизвестно, сколько именно знаков должна содержать искомая
подстрока, можно использовать спецсимволы, именуемые мудреным словом
квантификаторы (quantifiers). Например, можно написать "hel+o",
что будет означать слово, начинающееся с "he", со следующими за ним
одним или несколькими "1", и заканчивающееся на "о". Следует понимать,
что квантификатор относится к предшествующему выражению, а
не к отдельному символу. Полный список квантификаторов можно увидеть
в нижеприведенной таблице.
Символ Описание
* Соответствует 0 или более вхождений предшествующего выражения.
Например, 'zo*' соответствует "z" и "zoo".
+ Соответствует 1 или более предшествующих выражений. Например,
"zo+" соответствует "zo" и "zoo", но не "z".
? Соответствует 0 или 1 предшествующих выражений. Например,
'do(es)?' соответствует "do" в "do" или "does".
{n} n - неотрицательное целое. Соответствует точному количеству вхождений.
Например, 'о{2}' не найдет "о" в "Bob", но найдет два "о" в
"food".
{n,} n - неотрицательное целое. Соответствует вхождению, повторенному
не менее п раз. Например, *о{2,}' не находит "о" в "Bob", зато находит
все "о" в "foooood". 'о{1,}' эквивалентно 'о+'. *о{0,{' эквивалентно
'о*'.
{n,m} т и п - неотрицательные целые числа, где п "= т. Соответствует
минимум п и максимум m вхождений. Например, *о{1,3} находит три
первые "о" в "fooooood". 'о{0,1}' эквивалентно 'о?'. Пробел между
запятой и цифрами недопустим.
Концы и начала строк
Проверка начала или конца строки производится с помощью метасимволов
Л и $. Например, "Athing" соответствует строке, начинающейся с
"thing". "thing$" соответствует строке, заканчивающейся на "thing". Эти
символы работают только при включенной опции 's'. При выключенной
опции 's' находятся только конец и начало текста. Но и в этом случае
можно найти конец и начало строки, используя escape-последовательности
\А и \Z.
Граница слова
Для задания границ слова используются метасимволы '\Ъ' и '\В\
Regex re = new Regex("меня", "ms");
Работа со строками 233
В данном случае образец в re соответствует не только "меня" в строке
"найди меня", но и "меня" в строке "родители поменяли квартиру". Чтобы
избежать этого, можно предварить образец маркером границы слова:
Regex re - new Regex("\Ьменя", "шз");
Теперь будет найдено только "меня" в начале слова. Не стоит забывать,
что ВНУТРИ класса символов '\Ь' обозначает символ backspace (стирания).
Приведенные ниже в таблице метасимволы не заставляют машину
регулярных выражений продвигаться по строке или захватывать символы.
Они просто соответствуют определенному месту строки. Например,
Л определяет, что текущая позиция - начало строки. "AFTP' возвращает
только те "FTP", что находятся в начале строки.
Символ Значение
А Начало строки.
$ Конец строки, или перед \п в конце строки (см. опцию т).
\А Начало строки (ignores the m option).
\Z Конец строки, или перед \п в конце строки (игнорирует опцию т).
\z Точно конец строки (игнорирует опцию т).
\G Начало текущего поиска (часто это в одном символе за концом
последнего поиска).
\Ь На границе между \w (алфавитно-цифровыми) и \W (неалфавитноцифровыми)
символами. Возвращает true на первых и последних
символах слов, разделенных пробелами.
\В Не на \Ь-границе.
\w Слово. То же, что и [a-zA-Z_0-9].
\W Все, кроме слов. То же, что и [Aa-zA-Z_0-9].
\s Любое пустое место. То же, что и [ \f\n\r\t\v].
\S Любое непустое место. То же, что и [л \f\n\r\t\v].
\й Десятичная цифра. То же, что и [0-9].
YD He цифра. То же, что и [А0-9].
Вариации и группировка
Символ 'I' можно использовать для перебора нескольких вариантов.
Употребление его вместе со скобками - '(•••! •••!-••)' - позволяет создать
группы вариантов. Скобки используются для "захвата" подстрок для
дальнейшего использования и сохранения их во встроенных переменных
$1, $2,..., $9.
Regex re = new Regex("like (applesIpinesI bananas)");
MatchCollection me = re.Matches("I like apples a lot");
234 Раздел I I . Фундаментальные понятия
Такой пример будет работать и найдет последовательность "like apples",
поскольку "apples" - один из трех перечисленных вариантов. Скобки
также поместят "apples" в $1 как обратную ссылку для дальнейшего
использования. В основном это имеет смысл при замене.
ИСПОЛЬЗОВАНИЕ РЕГУЛЯРНЫХ ВЫРАЖЕНИЙ: Regex
Я думаю, с вас достаточно теории. Давайте перейдем к практике. .Net
технология обеспечивает объектно-ориентированный подход к обработке
регулярных выражений.
Библиотека классов для обработки регулярных выражений основывается
на пространстве имен System.Text.RegularExpressions. Главным классом
для обработки регулярных выражений является класс Regex, который
представляет собой компилятор регулярных выражений. Кроме того, Regex
обеспечивает множество полезных статических методов. Использование
Regex проиллюстрировано в следующем примере:
using System;
using System.Text;
using System.Text.RegularExpressions;
namespace Regular_Expressions
public class Tester
{
static void Main( )
{
string si = "Один,Два,Три, Строка для разбора";
Regex theRegex = new Regex(" I, I,");
StringBuilder sBuilder = new StringBuilder( );
inn id = 1;
foreach (string substring in theRegex.Split(si)}
f
sBuilder.AppendFormat( "{0}: {l}\n", id++, substring);
}
Console.WriteLine("{0)", sBuilder);
Результат работы программы будет представлен как:
1: Один
2: Два
3: Три
4: Строка
5: для
6: разбора
Работа со строками 235
Как вы могли заметить, в этом примере есть та же строка, что и в
примере для поиска подстроки "Один, Два, Три, Строка для разбора". Мы
объявили ее как si. Далее мы объявили регулярное выражение, которое
задает образец-разделитель для поиска:
Regex theRegex = new Regex(" I, I,");
В качестве образца используется выражение, объединенное оператором
ИЛИ. Ищется либо знак пробела, либо запятая, либо идущие подряд
запятая и пробел. Строка, задающая регулярное выражение, передается в
качеств параметра конструктору объекта theRegex.
Класс Regex содержит метод Split, который по своему действию напоминает
метод string.Split. Он возвращает массив строк как результат поиска регулярного
выражения в строке. В теле цикла уже привычным для вас способом,
при помощи класса String Builder, формируется выходная строка.
Метод Split класса Regex перегружен и может использоваться в двух
вариантах. Первый из них был показан в предыдущем примере. Второй
способ - использование вызова статического метода.
using System;
using System.Text;
using System.Text.RegularExpressions;
namespace Regular_Expressions
{
public class Tester
{
static void Main( )
f
string si = "Один,Два,Три, Строка для разбора";
StringBuilder sBuilder = new StringBuiider( );
int id = 1;
f o r e a c h ( s t r i n g s u b s t r i n g i n R e g e x . S p l i t ( s i , " I, I , " ) )
{
sBuilder.AppendFormat( " (0 } : {1}\n", id+ + , substring);
)
Console.WriteLine("{0 J", sBuilder);
Результатом работы программы станет все тот же выходной массив
строк. Отличие этого примера от предыдущего лишь в том, что нам не
пришлось создавать экземпляр объекта Regex. В данном случае для поиска
использовался статический метод Regex.Split, который принимает два
параметра - строку, в которой будет производиться поиск, и строку с
регулярным выражением.
Кроме этого, метод Split перегружен еще двумя вариантами, которые
позволяют ограничить количество раз использования метода Split и задать
начальную позицию в строке для поиска.
236 Раздел I I . Фундаментальные понятия
Использование Match коллекций
Пространство имен RegularExpressions содержит два класса, которые
позволяют осуществлять итерационный поиск в строке и возвращать
результат в виде коллекции. Коллекция возвращается в виде объекта типа
MatchCollection, содержащего объекты типа Match. Объект Match заключает
в себе два очень важных свойства, которые определяют его длину (Length)
и значение (Value). Давайте рассмотрим пример использования итерационного
поиска:
using System;
using System.Text;
using System.Text.RegularExpressions;
namespace Regular_Expressions
i
class Test
{
public static void Main( )
{
string si = "Это строка для поиска";
// найти любой пробельный символ
// следующий за непробельным
Regex theReg = new Regex(@"(\S+)\s");
// получить коллекцию результата поиска
MatchCollection theMarches =
theReg.Matches fsl);
// перебор всей коллекции
foreach (Match theMatch in theMatches)
f
Console.WriteLine( "theMatch.Length: {0}",
theMatch.Length);
if (theMatch.Length != 0)
(
Console.WriteLine("theMatch: {0}",
theMatch.ToString( ));
Результат работы программы:
theMatch.Length: 4
theMatch: Это
theMatch.Length: 7
Работа со строками 237
theMatch: строка
theMatch.Length: 4
theMatch: для
Давайте рассмотрим программу подробнее. Создаем простую строку
для поиска:
string si = "Это строка для поиска";
Затем формируем регулярное выражение:
Regex theReg = new Regex(@"(\S+)\s");
Это пример простейшего регулярного выражения. (\S) означает любой
непробельный символ. Знак (+), стоящий после (\S), означает, что может
быть любое количество непробельных символов. (\s) в нижнем регистре-
пробельный символ. В целом, это выражение означает: "Найти все
наборы, которые начинаются с непробельного символа и заканчиваются
пробельным".
Результат программы отображает лишь три первых слова исходной
строки. Четвертое слово не вошло в результирующую коллекцию, потому
что после него нет пробельного символа. Если вы добавите пробел в конце
предложения, то слово "поиска" также будет найдено и выведено в качестве
результата.
Использование групп
Класс Regex позволяет объединять регулярные выражения в группы.
Это бывает очень полезно, если необходимо выбрать из исходной строки
все подстроки, удовлетворяющие определенной категории, и таких категорий
несколько. Например, нужно выбрать все подстроки, которые могут
являться IP адресами и объединить их вместе. Для этого существует
класс Group. Любое регулярное выражение может быть добавлено в группу
и представлять свою группу по имени. Чтобы не запутаться, давайте
перейдем к примеру.
Для начала необходимо уяснить, как создавать группу. Например, для
того чтобы создать группу, определяющую IP адрес, вы можете создать
следующее регулярное выражение:
@ " ( ? " i p " ( \ d | \ . ) + ) \ s "
Имя группы задается в о скобках, перед которыми ставится знак (?).
Далее следует описание регулярного выражения, определяющего группу.
Класс Match явлется производным от класса Group и содержит коллекцию
объектов Group, к которым можно обратиться через свойство Groups.
using System;
using System.Text.RegularExpressions;
namespace Regular_Exprassions
(
class Test
{
public static void Main( )
238 Раздел I I . Фундаментальные понятия
string stringl = "04:03:27 127.0.0.0 GotDotNet.ru";
// группа time = одна и более цифр или двоеточий
// за которым следует пробельный символ
Regex theReg = new Regex(@"(?"время"(\dI\:)+)\s" +
// группа ip адрес - одна и более цифр или точек
// за которым следует пробельный символ
@ " ( ? " i p " ( \ d l \ , ) + ) \ Б " +
// группа url = один и более непробельных символов
@" (?"url"\S + )");
// получаем коллекцию поиска
MatchCollection theMatches =
theReg.Matches (stringl);
// перебор всей коллекции
foreach (Match theMatch in theMatches)
{
if (theMatch.Length != 0?
(
// выводим найденную подстроку
Console.WriteLine("\ntheMatch: {0)",
theMatch.ToString ( ));
// выводим группу "time"
Console.WriteLine ("время: {0}",
theMatch.Groups["время"]);
// выводим группу "ip"
Console.WriteLine("ip: {0)",
theMatch.Groups["ip"]);
// выводим группу "url"
Console.WriteLine("url: {0}",
theMatch.Groups["url"]);
Результат работы программы:
theMatch: 04:03:27 127.0.0.0 GotDotNet.ru
время: 04:03:27
ip: 127.0.0.0
url: GotDotNet.ru
Вначале мы создали строку для поиска:
String stringl = "04:03:27 127.0.0.0 GotDotNet.ru
Работа со строками 239
Эта строка очень простая. Она содержит по одному экземпляру элементов
каждой группы: "время", "ip" и "url". Этим группам соответствуют
подстроки "04:03:27", "127.0.0.0", "GotDotNet.ru". Но вместо этой строки
может быть использована любая другая, например текстовый файл или
запрос из базы данных.
Далее в программе создаются группы:
Regex theReg = new Regex{
@" (?"время"(\dl\:)+"\s" +
@"(?"ip"(\dl\.)+)\s" +
@" (?"url"\S+)");
Здесь создаются три группы: "время", "ip" и "url". Заметьте одну очень
важную особенность: можно создавать группы и называть их именами,
составленными из букв русского алфавита. Давайте рассмотрим более
подробно, каким образом создаются группы.
"время" - это название группы. Все, что следует после названия группы
и до закрывающей скобки, является регулярным выражением, описывающим
группу.
(?"время"(\д|\:)+)
В нашем случае группы разделяются пробельными символами. Точно
так же задается группа ip и группа url. Возможно, наши правила описания
групп не являются исключительными, но они подойдут для тестового
примера.
MatchCoIlection theMatches = theReg.Matches(stringl);
Здесь происходит поиск совпадений описанных регулярным выражением
в строке stringl.
Если длина объекта Match превышает значение 0, значит, соответствие
найдено. И результат выводится на экран:
Console.WriteLine("\ntheMatch: (0)", theMatch.ToString( ) ) ;
Далее выводится значение группы "время".
Console.MriteLine("время: {0}", theMatch.Groups["время"]);
Для этого при помощи строкового индексатора выбирается из GroupCollection
группа "время". Затем выводятся значения групп "ip" и "url". Я
уже приводил результат работы этой программы. А вот что будет, если
строку stringl проинициализировать по-другому. Например, так:
string stringl =
"04:03:27 127.0.0.0 GotDotNec.ru " +
"04:03:28 127.0.0.0 RSDN.ru " +
"04:03:29 127.0.0.0 Yandex.ru";
В этом случае на экран будет выведен следующий результат:
theMatch: 04:03:27 127.0.0.0 GotDotNet.ru
время: 04:03:27
ip: 127.0.0.0
url: GotDotNet.ru
theMatch: 04:03:28 127.0.0.0 RSDN.ru
240 Раздел I I . Фундаментальные понятия
время: 04:03:28
ip: 127ЛО.0
url: RSDN.ru
theMatch: 04:03:29 127.0.0.0 Yandex.ru
время: 04:03:29
ip: 127.0.0.0
url: Yandex.ru
В этом случае Match Col lection содержит три объекта, каждый из которых
будет выведен на экран. Вы имеете возможность выбирать, что
выводить на экран. Это может быть либо полное соответствие выражения,
либо определенная группа.
Использование CaptureCollection
Каждый раз, когда объект Regex находит подвыражение, создается
экземпляр объекта Capture и добавляется в CaptureCollection. Каждый Cupture
объект представляет собой результат единичного поиска. Каждая группа
имеет свою CaptureCollection, содержащую подвыражение, соответствующее
группе.
Ключевым свойством объекта Capture является его длина, или свойство
Length, которое представляет собой длину захваченной строки. Обращаясь
к свойству Match.Length, на самом деле вы обращаетесь к свойсту
Length объекта Capture, потому что имеет место наследование Match от
Group, a Group от Capture.
Объектная модель классов, работающих с регулярными выражениями,
позволяет объектам icnacca Match обращаться к свойствам и методам
дочерних классов. В этом смысле объект Group может представлять собой
Capture как объединение объектов Capture в единое целое. Объект класса
Match инкапсулирует в себе все группы соответствующего поиска по регулярному
выражению.
Обычно вам придется иметь дело лишь с одним объектом Capture в
CaptureCollection. Но не всегда. Иногда бывает полезно обрабатывать все
элементы CaptureCollection. Например, что будет, если в группу попадет
несколько экземпляров некоторой подстроки. Давайте изменим предыдущий
пример, добавив в строку регулярного выражения группу company.
И поместим два экземпляра такой группы в строку с регулярным выражением:
Regex theReg = new Regex(
@" ( ? " в р е м я " ( \ d | \ : ) + ) \ s " +
@" (?"conipany"\S + ) \ s " +
@" ( ? " c o m p a n y " \ S + ) \ s " ) ;
Такое регулярное выражение захватывает любое соответствие, начинающееся
с группы "время", затем может следовать произвольный набор
литеральных символов, затем группа "ip", затем опять набор литеральРабота
со строками 241
ных символов, заканчивающихся пробелом. Например, разбор следующей
строки даст положительный результат:
theMatch: 04:03:27 Double 127.0.0.0 Foo
время: 04:03:27
ip: 127.0.0.0
company: Foo
Но ведь это не совсем то, что мы хотели увидеть. Объект theMatch
содержит два экземпляра подстроки, соответствующей групп
...Закладка в соц.сетях