42726

Строки и регулярные выражения

Лабораторная работа

Информатика, кибернетика и программирование

String Работа с функциями класса StringBuilder Работа с регулярными выражениями. В C есть тип string но класс System. Пример использования: String s= qqq ; int k=s. Пример использования: nmespce test { clss Test { public sttic void Min { String s1= rbour s2= ce s3= zote ; System.

Русский

2013-10-30

300 KB

81 чел.

ЛАБОРАТОРНАЯ РАБОТА №2

ПО ДИСЦИПЛИНЕ «ТЕХНОЛОГИЯ ПРОГРАММИРОВАНИЯ»

Тема занятия:

Строки и регулярные выражения:

  1.  Работа с функциями класса System.String
  2.  Работа с функциями класса StringBuilder
  3.  Работа с регулярными выражениями. Поиск в тексте фрагментов по определенному шаблону

  1.  Теоретическое введение

1.1  Работа с функциями класса System.String

Строки в C# - это экземпляры класса System.String. В C# есть тип string, но класс System.String яляется более мощным, так что его использование часто оказывается более оправданным и простым. Этот класс имеет множество методов и свойств, некоторые из которых перечислены ниже:

1.1.1 Свойство Length

Возвращает длину строки. Пример использования:

           String s="qqq";

           int k=s.Length; //В k запишется 3

1.1.2 Свойство Compare

Статический метод, сравнивающий две строки. Возвращает 0, есть строки равны, отрицательное значение, если первая строка меньше второй и положительное значение, если первая строки больше второй (больше и меньше в алфавитном смысле, разумеется). Пример использования:

namespace test

{

   class Test

   {

       public static void Main()

       {

           String s1="arbour", s2="ace", s3="azote";

           System.Console.WriteLine(String.Compare(s1, s1)); //Выдаст 0, т. к. "arbour" равно "arbour".

           System.Console.WriteLine(String.Compare(s1, s2)); //Выдаст -1, т. к. "arbour" меньше "ace".

           System.Console.WriteLine(String.Compare(s1, s3)); //Выдаст 1, т. к. "arbour" больше "azote".

       }

   }

}

1.1.3 Метод Equals

Метод, возвращает true, если строки равны, false - если не равны. Пример использования:

  String s1="qqq", s2="www";

  System.Console.WriteLine(String.Equals(s1, s2).ToString());

1.1.4 Метод Substring

 Поволяет извлечь из строки подстроку. Пример использования:

    String s1="abcdefg", s2;

    s2=s1.Substring(3, 2);

    System.Console.WriteLine(s2); //Напечатается "de"

Где: первый параметр- означает, с какого места извлекаем (нумерация с нуля), а второй - сколько символов извлекаем.

1.1.5 Метод Insert

Вставляет в строку другую строку. Пример использования:

   

String s1="abcdefg", s2;

s2=s1.Insert(1, "xyz");

System.Console.WriteLine(s2); //Напечатается "axyzbcdefg"

Где, первый параметр означает, куда вставляем подстроку(нумерация, как  всегда, с нуля), второй - что за подстроку вставляем.

1.1.6 Метод IndexOf

Позволяет найти в строке подстроку. Пример использования:

  String s1="abcabcab", s2="bc", s3="zzz";

  System.Console.WriteLine(s1.IndexOf(s2)); //Напечатается 1

  System.Console.WriteLine(s1.IndexOf(s3)); //Напечатается -1

Этот метод возвращает номер позиции, на котором в строке находится передаваемая в качестве параметра подстрока. Если такой подстроки нет, то возвращается -1.

1.1.7 Метод Replace

Производит замену в строке. Пример использования:

   String s1="abcabcab", s2="bc", s3;

   s3=s1.Replace(s2, "q");

   System.Console.WriteLine(s3); //Напечатается aqaqab

1.1.8 Методы EndWith и StartsWith

 Проверяют, не завершается ли или не начинается ли строка с или на заданную строку соответственно. Пример использования:

          

 String s1="arbour";

     if(s1.StartsWith("ar"))

        System.Console.WriteLine("Строка начинается на \"ar\"");

     else

        System.Console.WriteLine("Строка не начинается на \"ar\"");

1.1.9 Методы ToUpper и ToLower 

Переводят строку в верхний или нижний регистр соответственно. Пример использования:

           String s1="aRbRur";

           s1=s1.ToLower();

1.1.10 Методы Trim, TrimEnds и TrimStart

Удаляют пробельные символы из начала и конца строки (Trim), только с конца строки (TrimEnds) и только с начала строки (TrimStart). Пример использваония:

           String s1="  ar  brur ";

           System.Console.Write(s1.Trim());

При изменении строки фактически старый экземпляр класса System.String уничтожается, и создается новый с там же именем и измененным содержанием. Это означает, что при интенсивной работе со строками программа может работать не так быстро, как хотелось бы. Если мы не хотим, что бы каждый раз создавался новый экземпляр класса, то вместо класса System.String надо использовать класс StringBuilder.

1.1.10. Методы Join и Split

Методы Join и Split выполняют над строкой текста взаимно обратные преобразования. Динамический метод Split позволяет осуществить разбор текста на элементы. Статический метод Join выполняет обратную операцию, собирая строку из элементов.

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

Динамический метод Split, как обычно, перегружен. Наиболее часто используемая реализация имеет следующий синтаксис:

public string[] Split(params char[])

На вход методу Split передается один или несколько символов, интерпретируемых как разделители. Объект string, вызвавший метод, разделяется на подстроки, ограниченные этими разделителями. Из этих подстрок создается массив, возвращаемый в качестве результата метода. Другая реализация позволяет ограничить число элементов возвращаемого массива.

Синтаксис статического метода Join:

public static string Join(string delimiters, string[] items )

В качестве результата метод возвращает строку, полученную конкатенацией элементов массива items, между которыми вставляется строка разделителей delimiters. Как правило, строка delimiters состоит из одного символа, который и разделяет в результирующей строке элементы массива items; но в отдельных случаях ограничителем может быть строка из нескольких символов.

Рассмотрим примеры применения этих методов. В первом из них строка представляет сложноподчиненное предложение, которое разбивается на простые предложения. Во втором предложение разделяется на слова. Затем производится обратная сборка разобранного текста. Вот код соответствующей процедуры:

public void TestSplitAndJoin()

{

  string txt = "А это пшеница, которая в темном чулане

     хранится," +" в доме, который построил Джек!";

  Console.WriteLine("txt={0}", txt);

  Console.WriteLine("Разделение текста на простые предложения:");

  string[] SimpleSentences, Words;

  //размерность массивов SimpleSentences и Words

  //устанавливается автоматически в соответствии с

  //размерностью массива, возвращаемого методом Split

  SimpleSentences = txt.Split(',');   

  for(int i=0;i< SimpleSentences.Length; i++)

     Console.WriteLine("SimpleSentences[{0}]= {1}",

        i, SimpleSentences[i]);

  string txtjoin = string.Join(",",SimpleSentences);

  Console.WriteLine("txtjoin={0}", txtjoin);

  Words = txt.Split(',', ' ');   

  for(int i=0;i< Words.Length; i++)

     Console.WriteLine("Words[{0}]= {1}",i, Words[i]);

  txtjoin = string.Join(" ",Words);

  Console.WriteLine("txtjoin={0}", txtjoin);

}//TestSplitAndJoin


Результаты выполнения этой процедуры показаны на рис. 1.1.

Рисунок 1.1 – Результат применения методов  Split и Join 

1.2 Класс StringBuilder

Класс StringBuilder принадлежит пространству имен System.Text.

Этот класс работает быстрее, чем класс String, так как при изменении строки, созданной как экземпляр класса String, создается каждый раз новый экземпляр класса, а старый уничтожается, при использовании же класса StringBuilder расходов на создание-уничтожение экземпляра класса нет -  работа всегда происходит с одним экземпляром.

Для этого класса нельзя использовать простое присваивание:

   StringBuilder s="abc"; //Неправильно!

В этом случае надо выполнять следующие  действия:

 StringBuilder s=new StringBuilder("abc"); //Правильно

У класса StringBuilder нет статических методов. Все его методы - динамические. Ниже перечислены основные свойства и методы класса StringBuilder:

1.2.1 Свойство Length

Возвращает длину строки. Пример использования:

   int k=s.Length;

1.2.2 Свойство  MaxCapacity

Свойство только для чтения. Дает максимальное количество символов, которые можно записать в объект типа StringBuilder. Пример использования:

   System.Console.WriteLine(s.MaxCapacity);

1.2.3 Метод Append

Прибавляет строку к существующей. Пример использования:

     StringBuilder s1=new StringBuilder("Cogito ");

  StringBuilder s2=new StringBuilder("ergo ");

       s1.Append(s2);

       s1.Append("sum");

       System.Console.WriteLine(s1); //Напечатается "Cogito ergo sum"

1.2.4 Метод Equals

Служит для сравнения двух строк. Возвращает true или false. Пример использования:

   if(s1.Equals(s2))

       System.Console.WriteLine("Строки равны");

   else

       System.Console.WriteLine("Строки не равны");

1.2.5 Метод Insert

Вставляет символы в заданную позицию (Нумерация идет с нуля). Пример использования:

StringBuilder s1=new StringBuilder("abcde");

s1.Insert(2, "xyz");

System.Console.WriteLine(s1); //Напечатается "abxyzcde"

1.2.6 Метод Remove

Удаляет символы из строки. Пример использования:

 StringBuilder s1=new StringBuilder("abcde");

 s1.Remove(1, 2);

 System.Console.WriteLine(s1); //Напечатается "ade"

Певый параметр - это с какой позиции удаляем (нумерация с нуля), второй - сколько символов удаляем.

1.2.7. Метод Replace

Заменяет символы. Пример использования:

      StringBuilder s=new StringBuilder("abcdeabcde");

    s.Replace("abc", "ZZZ");

    System.Console.WriteLine(s); //Напечатается "ZZZdeZZZde"

1.3 Регулярные выражения

ПРИМЕЧАНИЕ: Описание регулярных выражений скопировано из книги Павловской Т.А. «С# . Программирование на языке высокого уровня»

Регулярные выражения предназначены для обработки текстовой информации и обеспечивают:

  •  эффективный поиск в тексте по заданному шаблону;
  •  редактирование, замену и удаление подстрок;
  •  формирование итоговых отчетов по результатам работы с текстом.

С помощью регулярных выражений удобно обрабатывать, например, файлы в формате HTML, файлы журналов или длинные текстовые файлы. Для поддержки регулярных выражений в библиотеку .NET включены классы, объединенные в пространство имен System.Text.RegularExpressions.

1.3.1 Метасимволы

Регулярное выражение — это шаблон (образец), по которому выполняется поиск соответствующего ему фрагмента текста. Язык описания регулярных выражений состоит из символов двух видов: обычных и метасимволов. Обычный символ представляет в выражении сам себя, а метасимвол — некоторый класс символов, например любую цифру или букву.

Например, регулярное выражение для поиска в тексте фрагмента «Вася» записывается с помощью четырех обычных символов Вася, а выражение для поиска двух цифр, идущих подряд, состоит из двух метасимволов \d\d.

С помощью комбинаций метасимволов можно описывать сложные шаблоны для поиска. Например, можно описать шаблон для IP-адреса, адреса электронной почты, различных форматов даты, заголовков определенного вида и т. д.

ПРИМЕЧАНИЕ Синтаксис регулярных выражений .NET в основном позаимствован из языка Perl 5.  В таблице 1 описаны наиболее употребительные метасимволы, представляющие собой классы символов.

Метасимволы, перечисленные в таблице 2 , уточняют позицию в строке, в которой следует искать совпадение с регулярным выражением, например, только в начале или в конце строки. Эти метасимволы являются мнимыми, то есть в тексте им не соответствует никакой реальный символ.

Таблица 1. Классы символов

Класс символов

Описание

Пример

.

Любой символ, кроме \n

Выражение с.t соответствует фрагментам cat, cut, clt, c{t и т. д.

[]

Любой одиночный символ из последовательности, записанной внутри скобок. Допускается использование диапазонов символов

Выражение c[aul]t соответствует фрагментам cat, cut и clt, а выражение c[a-z]t — фрагментам cat, cbt, cct, celt,..., czt

[^]

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

Выражение c[^aul]t соответствует фрагментам cbt, c2t, cXt и т. д., а выражение c[^a-zA-Z]t — фрагментам cиt, c1t, cЧt, c3t и т. д.

\w

Любой алфавитно-цифровой символ, то есть символ из множества прописных и строчных букв и десятичных цифр

Выражение c\wt соответствует фрагментам cat, cut, clt, cЮt и т. д., но не соответствует фрагментам c{t, c;t и т. д.

\W

Любой не алфавитно-цифровой символ, то есть символ, не входящий в множество прописных и строчных букв и десятичных цифр

Выражение c\Wt соответствует фрагментам c{t, c;t, с t и т. д., но не соответствует фрагментам cat, cut, clt, cЮt и т. д.

\s

Любой пробельный символ, например символ пробела, табуляции (\t, \v), перевода строки (\n, \r), новой страницы (\f)

Выражение \s\w\w\w\s соответствует любому слову из трех букв, окруженному пробельными символами

\S

Любой не пробельный символ, то есть символ, не входящий в множество пробельных

Выражение \s\S\S\s соответствует любым двум непробельным символам, окруженным пробельными

\d

Любая десятичная цифра

Выражение c\dt соответствует фрагментам c1t, c2t,..., c9t

\D

Любой символ, не являющийся десятичной цифрой

Выражение c\Dt не соответствует
фрагментам с1
t, c2t, ..., c9t

Таблица 2. Уточняющие метасимволы

Метасимвол

Описание

^

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

$

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

\A

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

\Z

Фрагмент, совпадающий с регулярным выражением, следует искать только в конце многострочной строки

\b

Фрагмент, совпадающий с регулярным выражением, начинается

или заканчивается на границе слова (то есть между символами, соответствующими метасимволам \w и \W)

\B

Фрагмент, совпадающий с регулярным выражением,  не должен встречаться на границе слова

           Например, выражение ^cat соответствует символам cat, встречающимся в начале строки, выражение cat$ — символам cat, встречающимся в конце строки(то есть  за ними идет символ перевода строки), а выражение ^$ представляет пустую  строку, то есть начало строки, за которым сразу же следует ее конец.

В регулярных выражениях часто используют повторители. Повторители – это  метасимволы, которые располагаются непосредственно после обычного символа или класса символов и задают количество его повторений в выражении. Например, если требуется записать выражение для поиска в тексте пяти идущих  подряд цифр, вместо метасимволов \d\d\d\d\d можно записать \d{5}. Такому выражению будут соответствовать фрагменты 11111, 12345, 53332 и т

Наиболее употребительные повторители перечислены в таблице 3.

Таблица 3  Повторители

Метасимвол

Описание

Пример

*

Ноль или более повторений предыдущего элемента

Выражение ca*t соответствует фрагментам  ct, cat, caat, caaaaaaaaaaat  и.т.д.

+

Одно или более повторений предыдущего элемента

Выражение ca+t соответствует фрагментам cat, caat, caaaaaaaaaaat и т.д.

?

Ни одного или одно повторение предыдущего элемента   

Выражение ca?t соответствует  фрагментам сt и cat

{n}

Ровно n повторений предыдущего элемента

Выражение ca{3}t соответствует фрагменту caaat, а выражение (cat){2} – фрагменту catcat   (круглые скобки служат для группировки символов)

{n.}

По крайней мере n повторений предыдущего элемента

Выражение са{3.}t соответствует фрагментам caaat, caaaat,  сaaaaaaaaat  и т.д.

{n.m}

От n до m повторений предыдущего элемента

Выражение са{2.4}t соответствует фрагментам caat, caaat и  сaaaat  

Помимо рассмотренных элементов регулярных выражений можно использовать конструкцию выбора из нескольких элементов. Варианты выбора перечисляются через вертикальную черту. Например, если требуется определить, присутствует ли в тексте хотя бы один элемент из списка «cat», «dog» и «horse», можно использовать выражение

cat|dog|horse

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

Примеры простых регулярных выражений:

  •  целое число (возможно, со знаком):  [-+]?\d+
  •  вещественное число (может иметь знак и дробную часть, отделенную точкой):      [-+]?\d+\..?\d*
  •  российский номер автомобиля (упрощенно): [A-Z]\d{3}[A-Z]{2}\d\dRUS

ВНИМАНИЕ

Если требуется описать в выражении обычный символ, совпадающий с каким-либо метасимволом, его предваряют обратной косой чертой. Так, для поиска в тексте символа точки следует записать \.., а для поиска косой черты — \\.

Например, для поиска в тексте имени файла cat.doc следует использовать регулярное выражение cat\.doc. Символ «точка» экранируется обратной косой чертой для того, чтобы он воспринимался не как метасимвол «любой символ» (в том числе и точка!), а непосредственно (Обратите внимание на то, что метасимволы регулярных выражений не совпадают с метасимволами, которые используются в шаблонах имен файлов, таких как *.doc).

Для группирования элементов выражения используются круглые скобки. Группирование применяется во многих случаях, например, если требуется задать повторитель не для отдельного символа, а для последовательности (это использовано в предыдущей таблице). Кроме того, группирование служит для запоминания в некоторой переменной фрагмента текста, совпавшего с выражением, заключенным в скобки. Имя переменной задается в угловых скобках или апострофах:

(?<имя_переменной>фрагмент_выражения)

Фрагмент текста, совпавший при поиске с фрагментом регулярного выражения, заносится в переменную с заданным именем. Пусть, например, требуется выделить из текста номера телефонов, записанных в виде nnn-nn-nn. Регулярное выражение для поиска номера можно записать так:

(?<num>\d\d\d-\d\d-\d\d)

При анализе текста в переменную с именем num будут последовательно записываться найденные номера телефонов.

Рассмотрим еще один вариант применения группирования — для формирования обратных ссылок. Все конструкции, заключенные в круглые скобки, автоматически нумеруются, начиная с 1. Эти номера, предваренные обратной косой чертой, можно использовать для ссылок на соответствующую конструкцию. Например,  выражение (\w)\l используется для поиска сдвоенных символов в словах  ( wall, mass, cooperate). Если написать просто \w\w, будут найдены все пары алфавитно-цифровых символов.

 

Круглые скобки могут быть вложенными, при этом номер конструкции определяется порядком открывающей скобки в выражении. Примеры:

(Bacя)\s+(должен)\s+(?<sum>\d+)\spy6\..\s+Hy что же ты.. \1

В этом выражении три подвыражения, заключенных в скобки. Ссылка на первое из них выполняется в конце выражения. С этим выражением совпадут, например, фрагменты:

Вася должен 5 руб. Ну что же ты, Вася

Вася   должен   53459 руб.  Ну что же ты. Вася

Выражение, задающее IP-адрес:

((\d{l,3}\.){3}\d{l.3})

Адрес состоит из четырех групп цифр, разделенных точками. Каждая группа может  включать от одной до трех цифр. Примеры IP-адресов: 212.46.197.69,   212. 194.5.106,    209.122.173.160. Первая группа, заключенная в скобки, задает весь адрес. Ей присваивается номер 1. В нее вложены вторые скобки, определяющие границы  для повторителя {3}.

Переменную, имя которой задается внутри выражения в угловых скобках, также  можно использовать для обратных ссылок в последующей части выражения. Например, поиск двойных символов в словах можно выполнить с помощью выражения (?<s>\w)\k<s>, где s — имя переменной, в которой запоминается символ,  \к — элемент синтаксиса.

В регулярное выражение можно помещать комментарии. Поскольку выражения  обычно проще писать, чем читать, это — очень полезная возможность. Комментарий либо помещается внутрь конструкции (?#), либо располагается, начиная от символа # до конца строки (Для распознавания этого вида комментария должен быть включен режим  х  RegexOptions.IgnorePatternWhitespace.).

1.3.2  Классы библиотеки .NET для работы с регулярными выражениями

Классы библиотеки .NET для работы с регулярными выражениями объединены в  пространство имен System.Text.RegularExpressions.

Начнем с класса Regex, представляющего собственно регулярное выражение. Класс является неизменяемым, то есть после создания экземпляра его корректировка не допускается. Для описания регулярного выражения в классе определено несколько перегруженных конструкторов:

  •  Regex () — создает пустое выражение;
  •  Regex(String) — создает заданное выражение;
  •  Regex(String, RegexOptions) — создает заданное выражение и задает параметры для  его обработки с помощью элементов перечисления RegexOptions (например, различать или не различать прописные и строчные буквы).

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

Regex rx= new Regex(@"\b(?<word>\w+)\s+(\k<word>)\b",

RegexOpti ons.IgnoreCase );

Поиск фрагментов строки, соответствующих заданному выражению, выполняется с помощью методов IsMatch, Match и Matches.

Метод IsMatch возвращает true, если фрагмент, соответствующий выражению, в заданной строке найден, и false в противном случае. В листинге 1  приведен пример поиска повторяющихся слов в двух тестовых строках. В регулярное выражение, приведенное ранее, добавлен фрагмент, позволяющий распознавать знаки препинания.        

Пример поиска в строке дублированных слов (методом IsMatch):

using System;

using System.Text.RegularExpressions;

public class Test

{     public static void Main()

 {

Regex r = new Regex( @"\b(?<word>\w+)[.,:;!? ]\s*(\k<word>)\b",

RegexOpti ons.IgnoreCase ):

string tst1 = "Oh, oh! Give me more!";

if ( r.IsMatch(tst1 ) )    Console.WriteLine( " tst1   yes" );

          else      Console.WriteLine( " tstl    no"    );

          string tst2="Oh give me, give me more!";

          if ( r.IsMatch(tst2)) Console.WriteLine("tst2 yes");

          else Console.WriteLine( " tst2 no"    );

}

}

Результат работы программы:

tstl    yes

tst2   no

Повторяющиеся слова в строке tst2 располагаются не подряд, поэтому она не соответствует регулярному выражению. Для поиска повторяющихся слов, расположенных в произвольных позициях строки, в регулярном выражении нужно всего-навсего заменить пробел (\s) «любым символом» (.):

Regex r = new Regex( @"\b(?<word>\w+)[.,:;!?].*(\k<word>)\b",

RegexOptions.IgnoreCase );

Метод Match класса Regex, в отличие от метода IsMatch, не просто определяет, произошло ли совпадение, а возвращает объект класса Match — очередной фрагмент, совпавший с образцом. Рассмотрим листинг 2, в котором используете этот метод.

Пример  выделения из строки слов и чисел (методом Match)

using System;

using System.Text.RegularExpressions;

public class Test

{

public static void Main()

{

string text  = "Салат - $4, борщ - $3, одеколон - $10.";

string pattern = @"(\w+) - \$(\d+)[.,]";

Regex r    = new Regex( pattern );

Match m    = r.Match( text );

int  total  =0;

while ( m.Success )

        {

 Console.WriteLineC m );

total += int.Parse( m.Groups[2].ToString() );

m = m.NextMatch();

}

Console.WriteLine( "Итого: $" + total );

    }

}

Результат работы программы:

Салат - $4,

борщ - $3,

одеколон - $10.

Итого: $17

При первом обращении к методу Match возвращается первый фрагмент строки, совпавший с регулярным выражением pattern. В классе Match определено свойство Groups, возвращающее коллекцию фрагментов, совпавших с подвыражениями в круглых скобках. Нулевой элемент коллекции содержит весь фрагмент, первый элемент — фрагмент, совпавший с подвыражением в первых скобках, второй элемент — фрагмент, совпавший с подвыражением во вторых скобках, и т. д. Если при определении выражения задать фрагментам имена, как это было сделано в предыдущем листинге, можно будет обратиться к ним по этим именам, например:

string pattern = @"(?'name'\w+) - \$(?'price'\d+)[.,]";

……………………

total += int.Parse( m.Groups["price"].ToString() );

ПРИМЕЧАНИЕ

Метод NextMatch класса Match продолжает поиск в строке с того места, на котором закончился предыдущий поиск.

Метод Matches класса Regex возвращает объект класса MatchCollection — коллекцию всех фрагментов заданной строки, совпавших с образцом.

Рассмотрим теперь пример применения метода Split класса Regex. Этот метод разбивает заданную строку на фрагменты в соответствии с разделителями, заданными с помощью регулярного выражения, и возвращает эти фрагменты в массиве строк. Пример разбиения строки на слова (методом Split)

using System;

using System.Collections.Generiс;

using System.Text.RegularExpressions;

public class Test

{     public static void Main()

  {

string text     = "Салат - $4, борщ -$3. одеколон - $10.";

string pattern   = "[- ,.]+";

Regex r      = new Regex( pattern );

List<string> words = new List<string>( r.Split( text ) );

foreach ( string word in words ) Console.WriteLine( word );

 }

}

Результат работы программы:

Салат

$4

борщ

$3

одеколон

$10

Метод Replасе класса Regex позволяет выполнять замену фрагментов текста. Определено несколько перегруженных версий этого метода. Вот как выглядит пример простейшего применения метода в его статическом варианте, заменяющего все вхождения символа $ символами у.е.

string text     = "Салат - $4, борщ -$3. одеколон - $10.";

string text1   = Regex.Replace(text,@”\$”,”у.е.”);

Другие версии метода позволяют задавать любые действия по замене с помощью  делегата MatchEvaluator, который вызывается для каждого вхождения     фрагмента, совпавшего с заданным регулярным выражением.

           ПРИМЕЧАНИЕ

Помимо классов Regex и Match в пространстве имен System.Text.RegularExpressions  определены вспомогательные классы, например, класс Capture — фрагмент, совпавший  с подвыражением в круглых скобках;  класс CaptureCollection — коллекция фрагментов, совпавших со всеми подвыражениями в текущей группе; класс Group                                        содержит коллекцию Capture для текущего совпадения с регулярным выражением и т.д.

В качестве более реального примера применения регулярных выражений
рассмотрим программу анализа файла журнала веб-сервера. Это текстовый файл, каждая строка которого содержит информацию об одном соединении с
Четыре строки файла приведены ниже:

ppp-48.pool-113.spbnit.ru - - [31/Мау/2002:02:08:32 +0400] "GET / HTTP/1.1” 200

2434 "http://www.priсе.ru/bin/price/firminfo_f?fid=10922&where=01&base=2

"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"

81.24.130.7 - - [31/May/2002:08:13:17 +0400] "GET /swf/menu.swf  HTTP/1.1” 200

4682 "-" "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98)"

81.24.130.7 - - [31/May/2002:08:13:17 +0400] "GET /swf/header.swf HTTP/ 1.1. 200

21244 "-" "Mozilla/4.0 (compatible; MSIE 5.01; Windows 98)"

gate.solvo.ru - - [31/May/2002:10:43:03 +0400] "GET / HTTP/1.0" 200 2422

"http://www.price.ru/bin/price/firminfo_f?fid=10922&where=01&base=l"   

 "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)"

Подобные файлы могут иметь весьма значительный объем, поэтому составление  итогового отчета в удобном для восприятия формате имеет важное значение. Если рассматривать каждую строку файла как совокупность полей, разделенных  пробелами, то поле номер 0 содержит адрес, с которого выполнялось соединение  с сервером, поле номер 5 — операцию (GET при загрузке информации), поле 8 -  признак успешности выполнения операции (200 —  успешно) и, наконец, поле 9 — количество переданных байтов.

Приведенная ниже программа формирует в формате НТМL отчет, содержащий таблицу адресов, с которых выполнялось обращение к серверу, и суммарное количество переданных байтов для каждого адреса (то есть выполняет анализ журнала веб-сервера).

using System;

using System.I0;

using System.Col1ections.Generi с;

using System.Text.RegularExpressions;

public class Test

{     public static void Main()

  {

          StreamReader f = new StreamReader( "access_log" );

         StreamWriter w = new StreamWriterC "report.htm" );

            Regex get = new Regex( "GET" );

            Regex r    = new Regex( " " );

         string s. entry;

         int value;

         string[] items     = new string[40];

         Dictionary<string,  int> table = new Dictionary<string, int>();

         while ( (s = f.ReadLine() ) != null )

{

         items = r.Split( s );

                  if ( get.IsMatch( items[5] ) && items[8] = = "200" )

{

entry = items[0];

value = int.Parse( items[9] );

                             if ( table.ContainsKey( entry ) ) table[entry] += value;

                            else                   table[entry]   = value;

              }

}

    f.Close();

    w.Write( "<html><head><title> Report </title></head><body>" +

         "<table border =1 <tr><td> Computer <td> Bytes </tr>" );

     foreach ( string item in table.Keys )

w.Write("<tr><td>{0}<td>{l}</tr>". item.table[item] );

w.Write( "</table></body>" ); w.Close();

}

}

Фрагмент результата работы программы показан на рисунке 2.

Computer

Bytes

ppp-48.poo-113.spbnit.ru

107039

test223.sovam.com

2422

210.82.124.83

20052

ipblock209-209-002.octetgroup.net

162781

81.24.130.7

7475б

gate.solvo.ru

ll3692

212.113.108.164

261199

Рисунок2. Фрагмент журнала веб-сервера

Файл access_log считывается построчно, каждая строка разбивается на поля, которые заносятся в массив items. Затем, если загрузка прошла успешно, о чем свидетельствуют значения GET и 200 полей 5 и 8, количество переданных байтов (поле 9) преобразуется в целое и заносится в хеш-таблицу по ключу, которым  служит адрес, хранящийся в поле 0.

Для формирования HTML-файла report.htm используются соответствующие теги. Файл можно просмотреть, например, с помощью Internet Explorer, Как видите, программа получилась весьма компактной за счет использования стандартных классов библиотеки .NET.

2  Примеры работы со строками

2.1 Пример работы с классом String

Рассмотрим пример программы шифрования методом Цезаря (модификация метода). Исходная строка модифицируется следующим образом – каждый символ заменяется на другой с ASCII-кодом, следующим в алфавитном порядке.

Последовательность действий:

  1.  Создайте приложение оконное приложение, изображенное на рисунке 3.

Рисунок 3 – пример программы шифрования по методу Цезаря

 Список используемых элементов управления приведен в таблице 4.

Таблица 4 Список используемых элементов управления

Элемент управления

Класс

Описание

Label1

Label

 Метка «Исходная строка»

Label2

Label

 Метка «Результат преобразования»

textBox1

TextBox1

Окно ввода исходной строки

textBox2

TextBox2

Окно вывода результата

Button1

Button

Командная кнопка «Выполнить»

  1.  Для события  Click кнопки Button1 запишите следующий программный код:

private void button1_Click(object sender, EventArgs e)

       {

           string s = textBox1.Text;

           for (int i='z';i>=(int)'a';i--)

           {

               char old1=(char) i;

               char new1=(char) (i+1);

               s=s.Replace(old1,new1);

           }

           for (int i='Z';i>=(int)'A';i--)

           {

               char old1=(char) i;

               char new1=(char) (i+1);

               s=s.Replace(old1,new1);

           }

           textBox2.Text=s;

       }

Класс String весьма мощный класс, но он является неизменяемым (о чем говорилось в разделе 1). То есть если однажды строковый объект инициализирован, он уже не может быть изменен. Методы и операции, модифицирующие содержимое строк, на самом деле создают новые строки, копируя при необходимости старые. В данном примере метод Replace() при вызове каждый раз создает новую строку. Следовательно, в результате такого процесса шифрования появляются строковые объекты, которые будут храниться в куче до тех пор пока сборщик мусора не уничтожит их.

Для того, чтобы справиться с этой проблемой и предусмотрен класс StringBuilder.

2.2 Пример работы с классом StringBuilder

Работу с классом StringBuilder рассмотрим на предыдущем примере. Оконное приложение изображено на рисунке 2, а  список элементов управления приведен в таблице 4.

Программный код для события Click кнопки Button1 имеет следующий вид:

private void button1_Click(object sender, EventArgs e)

       {

           StringBuilder s = new  StringBuilder(textBox1.Text);

           for (int i = 'z'; i >= (int)'a'; i--)

           {

               char old1 = (char)i;

               char new1 = (char)(i + 1);

               s = s.Replace(old1, new1);

           }

           for (int i = 'Z'; i >= (int)'A'; i--)

           {

               char old1 = (char)i;

               char new1 = (char)(i + 1);

               s = s.Replace(old1, new1);

           }

           textBox2.Text = s.ToString();

       }

В данном программном фрагменте используется метод StringBuilder.Replace(), который выполняет ту же работу, что и  String.Replace(), но без копирования строки.

2.3  Пример работы с регулярными выражениями

Рассмотрим пример программы, выполняющей подсчет количества слов в текстовом файле.

Последовательность действий:

  1.  Создайте приложение оконное приложение, изображенное на рисунке 4.

Рисунок 4 – Пример приложения

Список используемых элементов управления приведен в таблице 5.

Таблица 5 Список используемых элементов управления

Элемент управления

Класс

Описание

Button1

Button

Командная кнопка «Выбор файла»

Label1

Label

 Метка «Результат»

Label2

Label

 Метка «слов»

Label3

Label

 Метка «в файле»

openFileDialog1

openFileDialog

Невидимый элемент управления для выбора текстового файла

  1.  Для работы с файлами и регулярными выражениями добавьте пространство имен using System.IO и using System.Text.RegularExpressions;
  2.  Для события  Click кнопки Button1 запишите следующий программный код:

       private void button1_Click(object sender, EventArgs e)

       {

// Диалог выбора файла

          if(openFileDialog1.ShowDialog() == DialogResult.OK)

          {

// Открытие выбранного файла

               StreamReader f = new StreamReader(openFileDialog1.FileName);

               String pattern = @"\b(\w+)";

               String s;

               int total = 0;

               Regex r = new Regex(pattern);

// Чтение выбранного файла по строкам

               while ((s = f.ReadLine()) != null)

               {

                   Match m = r.Match(s);

// Поиск регулярного выражения в очередной строке

                   while (m.Success)

                   {

                       total++;

                       m = m.NextMatch();

                   }

               }

               f.Close();

               textBox1.Text = Convert.ToString(total);

           }

       }

3.Задания для самостоятельной работы

3.1. Задания для работы со строками

Вариант 1

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит каждое слово в обратном порядке.
  2.  Дана строка не более чем из шести произвольных различных символов. Разработать программу вывода всех возможных подстрок, составленных из символов данной строки

Вариант 2

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран только предложения, содержащие введенное с клавиатуры слово.
  2.  По правилам машинописи после запятой в тексте всегда ставится пробел. Составить программу исправления такого типа ошибок в тексте.

Вариант 3

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран слова, начинающиеся с гласных букв.
  2.  Даны три строки. Определить, можно ли из символов первых двух строк получить третью строку.

Вариант 4

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран только строки, содержащие двузначные числа.
  2.  Дан текст. Вывести слова, которые отличны от последнего слова и в них нет повторяющихся букв

Вариант 5

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит его на экран  меняя местами каждые два соседних слова.
  2.  Дан текст. Составить программу проверки правильности написания сочетаний «жи», «ши», «ча», «ща», «чу» и «щу». Исправить ошибки.

Вариант 6

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран  только предложения, не содержащие запятых.
  2.  Дан текст. Вывести слова, которые отличны от последнего слова и совпадают с начальным отрезком латинского алфавита (a, ab, abc, abed, ...)

Вариант 7

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и определяет, сколько  в нем слов, состоящих не более чем из четырех букв.
  2.  Дан текст. Вывести все различные слова.

Вариант 8

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран  только цитаты, то есть предложения, заключенные в кавычки.
  2.  Дан текст. Вывести слова, встречающиеся в тексте по одному разу.

Вариант 9

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран только предложения, состоящие из заданного количества слов.
  2.  Дан текст. Определить количество слов, в которых содержится хотя бы одна заданная буква

Вариант 10

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран слова текста, начинающиеся и оканчивающиеся на гласные буквы.
  2.  Даны две строки. Вывести буквы, встречающиеся и в той и в другой строках.

Вариант 11

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран только строки, не содержащие двузначных чисел.
  2.  Удалить среднюю букву при нечетной длине строки и две средние буквы при четной длине строки

Вариант 12

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран только предложения, начинающиеся с тире, перед которым могут находиться только пробельные символы.
  2.  Удвоить вхождение некоторой буквы в текст. Например, текст «мама папа» должен иметь вид — «маамаа паапаа».

Вариант 13

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит его на экран, заменив прописной каждую первую букву слов, начинающихся с гласной буквы.
  2.  Дан текст. Определить количество слов, начинающихся и оканчивающихся одной и той же буквой.

Вариант 14

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит его на экран, заменив цифры от 0 до 9 словами «ноль», «один», ..., «девять», начиная каждое предложение с новой строки.
  2.  Дан текст. Определить количество слов, являющихся палиндромами.

Вариант 15

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, находит самое длинное слово и определяет, сколько раз оно встретилось в тексте.
  2.  Дан текст. Вывести все слова, предварительно удалив из них все предыдущие вхождения последней буквы.

Вариант 16

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран сначала вопросительные, а затем восклицательные предложения.
  2.  Дан текст. Вывести все слова, предварительно оставив в слове только первые вхождения каждой буквы.

Вариант 17

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит его на экран, после каждого предложения добавляя, сколько раз встретилось в нем введенное с клавиатуры слово.
  2.  Дан текст. Вывести слова, которые отличны от последнего слова и буквы которых упорядочены по алфавиту.

Вариант 18

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран его предложения в обратном порядке.
  2.  Даны две строки. Определить, можно ли, переставляя символы в первой строке, получить вторую строку.

Вариант 19

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран сначала предложения, начинающиеся с однобуквенных слов, а затем все остальные.
  2.  Дан текст. Определить количество слов, которые содержат определенное число вхождений заданной буквы

Вариант 20

  1.  Написать программу, которая вводит текст, состоящий из нескольких предложений, и выводит на экран предложения, содержащие максимальное количество знаков пунктуации.
  2.  Подсчитать сумму цифр, встречающихся в строке

3.2  Задания по регулярным выражениям

Используя регулярные выражения, напишите следующие приложения:

  1.  Дан текстовый файл f  и строка s, Переписать в новый файл g все строки файла f, содержащие значения переменной s в качестве подстроки.
  2.  Дан текстовый файл. Вывести все слова, начинающиеся с согласных букв русского алфавита.
  3.  Дан текстовый файл. Вывести все слова, состоящие только из цифр.
  4.  Дан текстовый файл, Вывести на экран все встречающиеся в данном файле даты в формате DD.MM.YYYY
  5.  Дан текстовый файл, Вывести на экран все встречающиеся в данном файле номера сетевых адаптеров  в формате HH-HH-HH-HH-HH-HH (где H-шестнадцатеричная цифра).
  6.  Дан текстовый файл,  Подсчитать количество в данном файле пустых строк.
  7.  Дан текстовый файл f, слова s1 и s2, Переписать файл f в новый файл g, заменяя все слова s1 на s2.
  8.  Дан текстовый файл f. Выяснить, верно ли, что в данном файле больше групп букв, чем групп цифр.
  9.  Дан текстовый файл, Вывести на экран все встречающиеся в данном файле доменные имена (имена в формате www.xxx.xxx.ru , где x-любой символ латинского алфавита, количество символов может быть любым).
  10.  Дан текстовый файл. Вывести на экран количество предложений в данном файле.
  11.  Дан текстовый файл f. Переписать содержимое файла f в файл g, предварительно заменяя  первую букву каждого слова на заглавную.
  12.  Дан текстовый файл f. Вывести все различные слова.
  13.  Дан текстовый файл f. Найти число вхождение в данный файл предлога «не».
  14.  Дан текстовый файл, имеющий структуру «Фамилия И.О. - $оклад». Вывести на экран фамилия всех лиц, чей оклад превышает  $9000.
  15.  Дан текстовый файл, имеющий структуру «Фамилия И.О. – рост см – вес кг». Вывести на экран фамилии всех лиц, чей рост превышает  190 см.
  16.  Дан текстовый файл, имеющий структуру «Фамилия И.О. – рост см – вес кг». Вывести на экран фамилии всех лиц, чей вес превышает  100 кг.
  17.  Дан текстовый файл. Переписать в файл  g все строки, содержащие более 30 символов.
  18.  Дан текстовый файл. Определить, есть ли в файле строки, начинающиеся на букву «Т».
  19.  Дан текстовый файл. Переписать в файл  g все строки, заканчивающиеся восклицательным знаком.
  20.  Дан текстовый файл, имеющий структуру «Фамилия И.О. – улица – номер дома – квартира – номер телефона». Вывести на экран фамилии всех абонентов, проживающих на улице Реввоенсовета.


 

А также другие работы, которые могут Вас заинтересовать

72929. Анализ условий и особенностей предпринимательства в России 106.69 KB
  Ни для кого не является секретом тот факт, что основу рыночной экономики составляет частная собственность, которая позволяет развиться другим формам экономической деятельности, в частности, предпринимательской.
72930. Учение о бытии. Проблема бытия. Философское учение о развитии. Сознание. Познание. Творчество. Практика. Наука и научное познание 166.5 KB
  Основными принципами диалектики являются принцип всеобщей связи и принцип развития принцип тождества единства диалектики логики и теории познания принцип восхождения от абстрактного к конкретному принцип единства логического и исторического.
72931. Общество как объект философского анализа. Проблема периодизации всемирной истории. Личность и общество. Проблема свободы и ответственности личности. Будущее человечества (философский аспект) 243.5 KB
  В философии существуют разные точки зрения по вопросам относящимся к сущности общества причинам его развития движущим силам. Натурализм или географическое направление развитие общества определяется природными условиями климатом плодородием почвы богатством минеральных ресурсов и т.
72932. Философия как система теоретического знания и тип мировоззрения. История философии 141.5 KB
  Философия имеет ряд разделов: онтологию – учение о бытии, гносеологию – учение о познании, аксиологию – учение о ценностях. Выделяют социальную философию и философию истории, а также философскую антропологию – учение о человеке. Философия – это не все мировоззрение, а лишь одна из его форм.
72933. Динамічна анатомія 78.5 KB
  Локомоції — група рухів зі зміною площі опори й з переміщенням тіла з одного місця на інше. У цій групі виділяють 2 різновиду рухів. До першого відносять циклічні рухи, що складаються з окремих повторюваних циклів (хода, біг, плавання, лижні перегони, ковзанярський спорт, веслування й ін.).
72934. Ранние цивилизации: Египет, Передняя Азия, Индия, Китай 25.72 KB
  Самые первые государства на земле появляются в долинах крупных рек Нила, Тигра, Евфрата, там, где возможно было создать оросительные (ирригационные) системы – основу поливного земледелия. В долинах этих рек люди гораздо меньше, чем в других местах, зависели от природных условий, получали стабильные урожаи.
72935. Античная цивилизация. Древняя Греция 33.96 KB
  Самые высокие оценки греческой цивилизации не кажутся преувеличенными. Мысль о чуде греческой цивилизации вызвана скорее всего ее необычайно быстрым расцветов. Создание греческой цивилизации относится к эпохе культурного переворота VII V вв.
72936. Біосфера. Роль В.І.Вернадського у вивченні біосфери. Ноосфера 33.73 KB
  Жива речовина. Що принципово відрізняє нашу планету від будь-якої іншої планети Сонячної системи? Наявність життя. «Якби на Землі не було життя, — писав академік В. І. Вернадський, — обличчя її було б так само незмінним і хімічно інертним, як нерухоме обличчя Місяця, як інертні уламки небесних світил».