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

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

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

Начать курс

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

Регулярные выражения (regex) — это неотъемлемая часть арсенала любого разработчика, работающего с текстом. В Rust, который славится своей производительностью и безопасностью, работа с регулярными выражениями реализована через популярный крейт regex. Эта библиотека предоставляет быстрый и надежный способ поиска, извлечения и замены текстовых шаблонов.

В этой статье мы подробно разберем, как использовать регулярные выражения в Rust: от установки крейта до продвинутых техник. Вы узнаете, как проверять совпадения, извлекать данные, заменять текст и обрабатывать ошибки. Все примеры кода написаны на Rust и готовы к использованию.

1. Установка и подключение крейта regex

Для работы с регулярными выражениями в Rust необходимо добавить крейт regex в файл Cargo.toml:

[dependencies]
regex = "1"

После этого можно импортировать необходимые модули в код:

use regex::Regex;

Крейт regex автоматически компилирует регулярные выражения в эффективный внутренний формат, что обеспечивает высокую скорость работы.

2. Основные операции с regex в Rust

2.1 Проверка совпадения (is_match)

Метод is_match возвращает true, если строка содержит хотя бы одно совпадение с шаблоном:

use regex::Regex;

fn main() {
    let re = Regex::new(r"\d+").unwrap();
    let text = "Сегодня 25 декабря";

    if re.is_match(text) {
        println!("Строка содержит числа");
    } else {
        println!("Числа не найдены");
    }
}

Этот метод полезен для быстрой валидации: проверка, содержит ли строка email, телефон или другие шаблоны.

2.2 Поиск первого совпадения (find)

Метод find возвращает первое совпадение в виде структуры Match, которая содержит начало и конец совпадения:

use regex::Regex;

fn main() {
    let re = Regex::new(r"\b\w+@\w+\.\w+\b").unwrap();
    let text = "Мой email: user@example.com, а также admin@test.org";

    if let Some(mat) = re.find(text) {
        println!("Найден email: {}", mat.as_str());
        println!("Позиция: {}..{}", mat.start(), mat.end());
    }
}

Результат выполнения:

Найден email: user@example.com
Позиция: 11..27

2.3 Поиск всех совпадений (find_iter)

Для получения всех совпадений используется итератор find_iter:

use regex::Regex;

fn main() {
    let re = Regex::new(r"\d+").unwrap();
    let text = "Цены: 100, 250 и 500 рублей";

    for mat in re.find_iter(text) {
        println!("Число: {}", mat.as_str());
    }
}

Вывод:

Число: 100
Число: 250
Число: 500

3. Извлечение групп с помощью захватывающих скобок

Одна из мощнейших возможностей regex — захватывающие группы. Они позволяют извлекать части совпадения:

use regex::Regex;

fn main() {
    let re = Regex::new(r"(\w+)@(\w+)\.(\w+)").unwrap();
    let text = "user@example.com";

    if let Some(caps) = re.captures(text) {
        println!("Полный email: {}", &caps[0]);
        println!("Имя пользователя: {}", &caps[1]);
        println!("Домен: {}", &caps[2]);
        println!("Зона: {}", &caps[3]);
    }
}

Группы нумеруются с 1. Группа 0 — это всё совпадение целиком.

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

use regex::Regex;

fn main() {
    let re = Regex::new(r"(?P<name>\w+)@(?P<domain>\w+\.\w+)").unwrap();
    let text = "admin@test.org";

    if let Some(caps) = re.captures(text) {
        println!("Имя: {}", caps.name("name").unwrap().as_str());
        println!("Домен: {}", caps.name("domain").unwrap().as_str());
    }
}

4. Замена текста с помощью regex

4.1 Простая замена (replace)

Метод replace заменяет первое совпадение:

use regex::Regex;

fn main() {
    let re = Regex::new(r"Ржавый").unwrap();
    let text = "Ржавый — это язык системного программирования";
    let result = re.replace(text, "Rust");
    println!("{}", result);
}

Вывод:

Rust — это язык системного программирования

4.2 Замена всех совпадений (replace_all)

Для замены всех вхождений используйте replace_all:

use regex::Regex;

fn main() {
    let re = Regex::new(r"\b\d{3}\b").unwrap();
    let text = "Коды: 123, 456, 789";
    let result = re.replace_all(text, "***");
    println!("{}", result); // Коды: ***, ***, ***
}

4.3 Замена с использованием групп ($1, $2)

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

use regex::Regex;

fn main() {
    let re = Regex::new(r"(\w+)@(\w+)\.(\w+)").unwrap();
    let text = "user@example.com";
    let result = re.replace_all(text, "$1 at $2 dot $3");
    println!("{}", result); // user at example dot com
}

5. Обработка ошибок и производительность

Создание регулярного выражения может завершиться ошибкой, если синтаксис некорректен. Всегда обрабатывайте результат:

use regex::Regex;

fn main() {
    let pattern = r"[a-z"; // неправильный синтаксис
    match Regex::new(pattern) {
        Ok(re) => println!("Regex скомпилирован: {}", re),
        Err(e) => eprintln!("Ошибка компиляции regex: {}", e),
    }
}

Советы по производительности:

  • Компилируйте regex один раз и переиспользуйте его. Не создавайте новый экземпляр в цикле.
  • Используйте Regex::new в ста

Блоги

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