Введение: Регулярные выражения в 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в ста