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

Регулярные выражения дают возможность осуществить сложный поиск или замену в строке. В языке C++ использовать регулярные выражения позволяют классы и функции, объявленные в заголовочном файле regex. Не забудьте добавить следующую инструкцию в самое начало программы:

#include <regex>

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

Создать шаблон регулярного выражения позволяют классы regex и wregex, которые являются лишь псевдонимами шаблонного класса basic_regex:

typedef basic_regex<char> regex;
typedef basic_regex<wchar_t> wregex;

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

basic_regex();
basic_regex(const _Ch_type *cstr, flag_type flags=ECMAScript);
basic_regex(const _Ch_type *p, size_t len, flag_type flags=ECMAScript);
basic_regex(const basic_string &str, flag_type flags=ECMAScript);
basic_regex(<Итератор1>, <Итератор2>, flag_type flags=ECMAScript);

В параметре cstr указывается C-строка или L-строка:

std::regex rgx("^[0-9]+$");
std::wregex wrgx(L"^[0-9]+$");

Параметр len задает длину символьного массива p:

std::string s("^[0-9]+$");
std::regex rgx(s.data(), s.size());

В параметре str можно указать объекты классов string или wstring:

std::regex rgx(std::string("^[0-9]+$"));
std::wregex wrgx(std::wstring(L"^[0-9]+$"));

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

std::string s("^[0-9]+$");
std::regex rgx(s.cbegin(), s.cend());

В параметре flags можно указать следующие флаги или их комбинацию через оператор |:

static constexpr flag_type collate = regex_constants::collate;
static constexpr flag_type icase = regex_constants::icase;
static constexpr flag_type nosubs = regex_constants::nosubs;
static constexpr flag_type optimize = regex_constants::optimize;
static constexpr flag_type ECMAScript = regex_constants::ECMAScript;
static constexpr flag_type basic = regex_constants::basic;
static constexpr flag_type extended = regex_constants::extended;
static constexpr flag_type awk = regex_constants::awk;
static constexpr flag_type grep = regex_constants::grep;
static constexpr flag_type egrep = regex_constants::egrep;

Если указан флаг collate, то будут учитываться настройки локали, например, диапазон [а-я] зависит от настроек локали. По умолчанию в диапазон от а до я буква ё не попадает и ее нужно указывать дополнительно: [а-яё] (советую всегда так делать). Пример указания флага collate и проверки на полное соответствие шаблону с помощью функции regex_match():

std::setlocale(LC_ALL, "Russian_Russia.1251");
std::regex::flag_type flags =
            std::regex::collate | std::regex::ECMAScript;
std::regex rgx("[а-я]+", flags);
if (std::regex_match("ёж", rgx))
   std::cout << "Строка соответствует шаблону" << std::endl;
else std::cout << "Не соответствует" << std::endl;
// Результат: Строка соответствует шаблону

Если указан флаг icase, то поиск будет выполняться без учета регистра символов. Для русских букв нужно настроить локаль и указать флаг collate. Чтобы не зависеть от этого флага следует указывать диапазон так: [a-zA-Zа-яА-ЯёЁ] (этому диапазону соответствует любая латинская или русская буква независимо от регистра символов). Пример указания флага icase и проверки на полное соответствие шаблону с помощью функции regex_search():

std::regex::flag_type flags =
            std::regex::icase | std::regex::ECMAScript;
std::regex rgx("^[a-z]+$", flags);
std::cout << std::regex_search("String", rgx) << std::endl; // 1

Функции regex_match() и regex_search() возвращают значение true, если строка соответствует шаблону регулярного выражения, и false — в противном случае. При использовании функции regex_match() проверяется полное соответствие с шаблоном, поэтому привязки в началу (символ ^) и концу (символ $) строки можно не указывать. Функция regex_search() выполняет сравнение с любым фрагментом строки, поэтому для проверки полного соответствия шаблону нужно указывать привязки к началу и концу строки.

Если указан флаг nosubs, то найденные группы (фрагменты, заключенные в строке шаблона в круглые скобки) сохраняться не будут:

std::regex::flag_type flags =
            std::regex::nosubs | std::regex::ECMAScript;
std::regex rgx("([0-9]+) ([0-9]+) ([0-9]+)", flags);
std::cmatch m;
if (std::regex_search("12 34 56", m, rgx)) {
   for (size_t i = 0, size = m.size(); i < size; ++i) {
      std::cout << m[i] << std::endl;
   }
} // Результат: 12 34 56

Если не использовать флаг nosubs, то мы получим все три числа по отдельности:

12 34 56
12
34
56

Первая строка результата соответствует полному совпадению с шаблоном, а последующие числа — фрагментам, заключенным в строке шаблона в круглые скобки: ([0-9]+). В диапазон [0-9] попадают любые цифры, а метасимвол + указывает, что цифра должна встречаться один или более раз.

Флаги ECMAScript, basic, extended, awk, grep и egrep задают используемый синтаксис регулярного выражения. Можно указать только один из перечисленных флагов. По умолчанию используется флаг ECMAScript, который задает синтаксис регулярных выражений языка JavaScript. Именно этот синтаксис мы и будем изучать в этой книге.

Присвоить значение после создания объекта позволяет оператор =:

std::regex rgx;
rgx = "^[0-9]+$";
rgx = std::string("^[0-9]+$");

Можно также воспользоваться методом assign(). Основные прототипы метода:

basic_regex &assign(const _Ch_type *cstr, flag_type flags=ECMAScript);
basic_regex &assign(const _Ch_type *p, size_t len, flag_type flags);
basic_regex &assign(const basic_string &str, flag_type flags=ECMAScript);
basic_regex &assign(<Итератор1>, <Итератор2>,
                    flag_type flags=ECMAScript);

Пример:

std::regex rgx;
rgx.assign("^[0-9]+$");

Если регулярное выражение содержит ошибки, то генерируется исключение regex_error. Пример обработки исключения:

try {
   std::regex rgx("^[0-9]+$");
   std::cout << std::regex_search("10", rgx) << std::endl; // 1
} catch (std::regex_error &e) {
   std::cout << "Ошибка " << e.what() << std::endl;
}

Учебник C++ (MinGW-W64)
Учебник C++ (MinGW-W64) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов