Регулярные выражения в C++: мощный инструмент для работы со строками
Регулярные выражения (regex) — это формальный язык поиска и манипуляции подстроками в тексте на основе шаблонов. В C++ поддержка регулярных выражений появилась в стандарте C++11 и реализована в библиотеке <regex>. Это незаменимый инструмент для валидации данных, парсинга логов, поиска паттернов и замены текста.
В этой статье мы разберем основные функции библиотеки regex, научимся составлять шаблоны и рассмотрим практические примеры с кодом.
1. Основные типы и функции библиотеки <regex>
Для работы с регулярными выражениями в C++ используются три основных класса:
std::regex— представляет само регулярное выражение (шаблон).std::smatch— контейнер для хранения результатов поиска (для строк типаstd::string).std::cmatch— аналог для C-строк (const char*).
Ключевые функции для применения regex:
std::regex_match()— проверяет, соответствует ли вся строка шаблону.std::regex_search()— ищет первое совпадение с шаблоном в строке.std::regex_replace()— заменяет все совпадения на заданный текст.
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string text = "Мой номер: +7-123-456-78-90";
std::regex pattern(R"(\+7-\d{3}-\d{3}-\d{2}-\d{2})");
if (std::regex_search(text, pattern)) {
std::cout << "Номер найден!" << std::endl;
}
// Извлекаем совпадение
std::smatch match;
if (std::regex_search(text, match, pattern)) {
std::cout << "Найденный номер: " << match[0] << std::endl;
}
return 0;
}
2. Синтаксис регулярных выражений: метасимволы и квантификаторы
Шаблоны regex в C++ используют синтаксис, аналогичный ECMAScript (по умолчанию). Вот основные элементы:
- Точка (.) — любой одиночный символ, кроме перевода строки.
- Звездочка (*) — 0 или более повторений предыдущего символа.
- Плюс (+) — 1 или более повторений.
- Вопросительный знак (?) — 0 или 1 повторение (делает символ необязательным).
- Квадратные скобки ([]) — класс символов (например,
[0-9]— любая цифра). - Круглые скобки (()) — группировка и захват подстроки.
- Вертикальная черта (|) — логическое ИЛИ.
- Символ ^ — начало строки.
- Символ $ — конец строки.
Примеры квантификаторов:
\d{3}— ровно 3 цифры.\w{2,4}— от 2 до 4 буквенно-цифровых символов.[A-Za-z]+— одна или более латинских букв.
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string email = "user@example.com";
// Простой шаблон для email
std::regex email_pattern(R"([\w.+-]+@[\w-]+\.[\w.]+)");
if (std::regex_match(email, email_pattern)) {
std::cout << "Email корректен." << std::endl;
} else {
std::cout << "Email некорректен." << std::endl;
}
// Проверка номера телефона
std::string phone = "+7 (495) 123-45-67";
std::regex phone_pattern(R"(\+7\s?\(?\d{3}\)?\s?\d{3}-?\d{2}-?\d{2})");
if (std::regex_match(phone, phone_pattern)) {
std::cout << "Телефон корректен." << std::endl;
}
return 0;
}
3. Извлечение данных с помощью групп захвата
Группы захвата (capturing groups) позволяют не только найти шаблон, но и извлечь его части. Каждая группа обозначается круглыми скобками (). Доступ к группам осуществляется через объект std::smatch по индексу (нулевой индекс — всё совпадение, первый — первая группа и т.д.).
#include <iostream>
#include <regex>
#include <string>
int main() {
std::string log = "Ошибка: файл data.txt не найден (код 404)";
// Группы: 1 - тип сообщения, 2 - имя файла, 3 - код ошибки
std::regex pattern(R"((\w+):\s*файл\s*(\S+)\s*не найден\s*\(код\s*(\d+)\))");
std::smatch matches;
if (std::regex_search(log, matches, pattern)) {
std::cout << "Полное совпадение: " << matches[0] << std::endl;
std::cout << "Тип: " << matches[1] << std::endl;
std::cout << "Файл: " << matches[2] << std::endl;
std::cout << "Код ошибки: " << matches[3] << std::endl;
}
return 0;
}
Вывод программы:
Полное совпадение: Ошибка: файл data.txt не найден (код 404)
Тип: Ошибка
Файл: data.txt
Код ошибки: 404
4. Замена текста с помощью regex_replace
Функция std::regex_replace() позволяет заменить все вхождения шаблона на указанную строку.