Регулярные выражения в C++: полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Регулярные выражения в C++: мощный инструмент для работы с текстом

Регулярные выражения (regex) — это мощнейший инструмент для поиска, извлечения и замены текстовых фрагментов по заданному шаблону. В C++ поддержка регулярных выражений появилась в стандарте C++11 и реализована в заголовочном файле <regex>. В этой статье мы подробно разберем, как использовать регулярные выражения в C++ на практических примерах.

Основные компоненты библиотеки <regex>

Библиотека <regex> включает в себя несколько ключевых классов и функций:

  • std::regex — класс, представляющий скомпилированное регулярное выражение.
  • std::smatch — контейнер для хранения результатов поиска (для строк типа std::string).
  • std::regex_match — проверяет, соответствует ли вся строка шаблону.
  • std::regex_search — ищет первое вхождение шаблона в строке.
  • std::regex_replace — заменяет совпадения на указанный текст.

Рассмотрим каждый из этих компонентов на примерах.

Пример 1: Проверка соответствия строки шаблону (regex_match)

Функция std::regex_match возвращает true, если вся строка полностью соответствует регулярному выражению. Это идеально подходит для валидации данных, например, проверки email или номера телефона.

#include <iostream>
#include <regex>
#include <string>

int main() {
    std::string email = "user@example.com";
    // Шаблон для проверки email (упрощенный)
    std::regex pattern(R"([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})");
    
    if (std::regex_match(email, pattern)) {
        std::cout << "Email корректен." << std::endl;
    } else {
        std::cout << "Email некорректен." << std::endl;
    }
    
    // Пример с некорректным email
    std::string bad_email = "user@.com";
    if (std::regex_match(bad_email, pattern)) {
        std::cout << "Email корректен." << std::endl;
    } else {
        std::cout << "Email некорректен." << std::endl;
    }
    
    return 0;
}

В этом примере мы использовали сырую строку R"(...)", чтобы избежать экранирования обратных слешей. Шаблон проверяет, что строка содержит локальную часть, знак @, доменное имя и домен верхнего уровня.

Пример 2: Поиск подстроки в тексте (regex_search)

Если нужно найти первое вхождение шаблона внутри строки, используется std::regex_search. Результаты сохраняются в объекте std::smatch.

#include <iostream>
#include <regex>
#include <string>

int main() {
    std::string text = "Мой номер телефона: +7 (123) 456-78-90. Позвоните мне!";
    // Шаблон для поиска российского номера телефона
    std::regex phone_pattern(R"(\+7\s?\(?\d{3}\)?\s?\d{3}[- ]?\d{2}[- ]?\d{2})");
    std::smatch match;
    
    if (std::regex_search(text, match, phone_pattern)) {
        std::cout << "Найден номер: " << match.str() << std::endl;
        std::cout << "Позиция: " << match.position() << std::endl;
    } else {
        std::cout << "Номер не найден." << std::endl;
    }
    
    return 0;
}

Объект match содержит не только найденную строку, но и информацию о позиции вхождения. Метод match.str() возвращает найденный фрагмент, а match.position() — индекс начала совпадения в исходной строке.

Пример 3: Замена текста с помощью regex_replace

Функция std::regex_replace заменяет все вхождения шаблона на указанную строку. Можно использовать обратные ссылки (backreferences) вида $1, $2 и т.д. для подстановки захваченных групп.

#include <iostream>
#include <regex>
#include <string>

int main() {
    std::string text = "Сегодня 15.03.2024, а завтра будет 16.03.2024.";
    // Шаблон для даты в формате ДД.ММ.ГГГГ
    std::regex date_pattern(R"((\d{2})\.(\d{2})\.(\d{4}))");
    // Замена на формат ГГГГ-ММ-ДД
    std::string result = std::regex_replace(text, date_pattern, "$3-$2-$1");
    
    std::cout << "Исходный текст: " << text << std::endl;
    std::cout << "Результат: " << result << std::endl;
    
    // Удаление всех цифр из строки
    std::regex digit_pattern(R"(\d+)");
    std::string clean_text = std::regex_replace(text, digit_pattern, "");
    std::cout << "Текст без цифр: " << clean_text << std::endl;
    
    return 0;
}

Обратите внимание на синтаксис обратных ссылок: $1 соответствует первой захваченной группе (день), $2 — второй (месяц), $3 — третьей (год). Это позволяет гибко переформатировать текст.

Пример 4: Итерация по всем совпадениям (regex_iterator)

Для обработки всех вхождений шаблона в строке удобно использовать итератор std::sregex_iterator. Он позволяет перебрать все совпадения последовательно.

#include <iostream>
#include <regex>
#include <string>
#include <vector>

int main() {
    std::string text = "ID: 1234, ID: 5678, ID: 9012";
    // Шаблон для поиска чисел после "ID: "
    std::regex id_pattern(R"(ID:\s*(\d+))");
    
    std::vector<std::string                

Блоги

Рекомендаций по книгам