Добавил:
t.me Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

2 семестр / Литература / Язык программирования С++. Краткий курс. Страуструп

.pdf
Скачиваний:
9
Добавлен:
16.07.2023
Размер:
31.34 Mб
Скачать

9.4.

Регулярные

выражения

165

9.4.

Реrупярные

выражения

Регулярные

выражения

являются

мощным

инструментом

для

обработки

текста.

Они

обеспечивают

способ

простого

и

подробного

описания

шаблонов

в

тексте

(например,

почтовый

индекс

США,

такой

как

ТХ

77845,

или

дату

в

стиле

ISO,

например

2009-06-07)

и эффективного

поиска

таких

шаблонов.

В

заголовочном

файле

<regex>

стандартная

библиотека

обеспечивает

под­

держку

регулярных выражений

в

виде

класса

std:

:

regex

и

функций

под­

держки. Чтобы

попробовать библиотеку

regex

и выведем шаблон регулярного выражения

3

:

 

"на

зуб",

давайте

определим

11 Шаблон regex pat

почтового индекса США: XXddddd-dddd {R"(\w{2}\s*\d{5}(-\d{4})?)"};

и

его

варианты:

Программисты

практически

на

любом

языке,

которые

использовали

ре­

гулярные

выражения,

сочтут

строку

\w{

2}

\s*\d{

5}

(-\d{

4})?

знакомой.

Она

задает

шаблон,

начинающийся

с

двух

букв

\

w{

2},

за

которыми

следует

необязательный

пробел

\

s

*,

за

которым

следуют

пять

цифр

\ d {5 }

с

необя­

зательным

последующим

тире

и

четырьмя

цифрами

-\d{

4}.

Если

вы

не

зна­

комы

с

регулярными

выражениями,

то

сейчас

самое

время

познакомиться

с

ними, например, в книгах (55], (33] и [22].

Чтобы записать шаблон, я использую необработанный

строковый

литерал,

начинающийся

с

R11

(

и

заканчивающийся

}

11

Он

позволяет

использовать

об­

ратную

косую

черту

и

кавычки

в

строке

непосредственно,

без

специальных

последовательностей

символов.

Необработанные

строки

особенно

хорошо

подходят

для

регулярных

выражений,

потому

что

они,

как

правило,

содержат

много

обратных

косых

черт.

Если

бы

я

использовал

обычную

строку,

то

опре­

деление

шаблона

было

бы

следующим:

regex

pat

{"\\w{2}\\s*\\d{5}(-\\d{4})?"};

В заголовочном файле <regex>

держку регулярных выражений:

стандартная

библиотека

предоставляет

под­

regex_ma tch () : соответствует ли

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

(из­

вестного размера) (§9.4.2);

 

 

regex_ search () : поиск строки,

которая соответствует регулярному

выражению, в (произвольно длинном) потоке данных (§9.4.1 ).

 

3

В данном

случае

следует

отличать

шаблон

регулярного

выражения

(pattem)

от

шаблона

С++

(template).

Поскольку

из

контекста

понятно,

о

чем

именно

идет речь

в

том

или

ином

случае;

уточнения,

какой

именно

шаблон

имеется

в виду,

в

основном

опущены.

-

При­

меч.

пер.

cout

<<

"\t:

 

 

9.4. Регулярные

выражения

"

<<

matches[l] << '\n';

//

Подшаблон

167

Эта

функция

читает

файл

в

поисках

почтовых

индексов

США,

таких

как

ТХ77845

и

ОС

20500-0001.

Тип

smatch

-

контейнер

с

результатами

поис­

ка.

Здесь

ma

tches

[О]

-

это

весь

шаблон,

а

ma

tches

[

1]

-

необязательный

четырехзначный подшаблон.

 

Символ новой строки \n

может

быть

частью

шаблона,

поэтому

можно

ис­

кать

многострочные

шаблоны.

Очевидно,

если

мы

хотим

это

сделать,

нам

не

следует читать строки по одной.

Синтаксис и семантика регулярных

выражений

разработаны

таким

обра­

зом,

что

регулярные

выражения

могут

быть

скомпилированы

в

конечные

ав­

томаты

для

эффективного

выполнения

[14].

Тип

regex

выполняет

эту

компи­

ляцию

во

время

выполнения.

9.4.2.

Запись

регулярных

выражений

Библиотека

регулярных

выражений

regex

может

распознавать

несколько

вариантов

обозначений

для

регулярных

выражений.

Здесь

я

использую

стан­

дартную

запись,

вариант стандарта

ЕСМА,

используемый

в

ECMAScript

(бо­

лее известен как JavaScript).

Синтаксис регулярных выражений

основан

на

символах со

специальным

значением.

Специальные

символы

регулярных

выражений

Любой единственный символ

Начало класса символов Конец класса символов

Начало счеNика

Конец счеNика Начало группировки Конец группировки

\ * + ?

$

Следующий символ имеет особое значение

Нуль или большее количество (суффикс)

Один или большее количество (суффикс)

Необязателен (нуль или один) (суффикс)

Альтернатива (или)

Начало строки; отрицание Конец строки

Например,

мы

можем

указать

строку,

начинающуюся

с

нуля

или

более

символов А, за которыми

зательный символ С:

следует

одна

или

несколько

букв

В,

а

затем

-

необя­

лд*В+С?$

Вот

примеры

строк,

соответствующих

этому

регулярному

выражению:

9.4.

Регулярные

выражения

169

искать

кратчайшее

соответствие,

а

не

длиннейшее.

По

умолчанию

всегда

вы­

полняется

поиск

наидлиннейшего

соответствия;

этот

принцип

известен

как

правwю

наибольшего

соответствия

(Мах

Munch rule).

Рассмотрим

строку

аЬаЬаЬ

Шаблон

(аЬ)

+

находит

всю

строку

аЬаЬаЬ,

но

шаблон

(

аЬ)

+?

находит

только первое аЬ.

Наиболее распространенные

классификации

символов

имеют

имена.

alnum alpha Ьlank cntrl d digit graph lower print punct s space upper w xdigit

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

 

Любая буква или цифра

Любая буква

 

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

Любой управляющий символ

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

цифра

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

цифра

Любой графический символ

Любой символ в нижнем регистре

Любой выводимый символ

Любой символ пунктуации

Любой пробельный символ

Любой пробельный символ

Любой символ в верхнем регистре

Любой символ слова (буква, цифра или подчеркивание)

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

В

регулярных

выражениях

имя

класса

символов

должно

находиться

в

специальных

скобках-

[:

: ] .

Например,

[:

digi

t:]

соответствует

десятич­

ной

цифре.

Кроме

того,

они

должны

использоваться

в

паре

скобок

[ ] ,

опреде­

ляющей класс символов.

Для некоторых классов

символов

поддерживается

сокращенная

запись.

\d \s \w

Аббревиатуры для классов символов

Десятичная цифра

Пробельный символ (пробел, табуляция и т.п.)

Буква (a-z), цифра (0-9) или подчеркивание(_)

[[:digit:]] [[:space:]] [_[ :alnum:]]