Регулярните изрази са изключително полезен инструмент за обработка на низове във всеки език за програмиране. В Rust можем да използваме кутията regex за работа с регулярни изрази. Тази статия ще предостави задълбочено ръководство за използване на регулярен израз в Rust, включително синтаксис, примери и важни концепции, които трябва да знаете.

Въведение в Regex в Rust

Регулярният израз или „regex“ е модел, който може да съответства на низове или части от низове. Те са полезни за неща като:

  • Проверка на низ (имейл, URL и т.н.)
  • Разбор на низове
  • Търсене и замяна
  • И още много

За да използваме регулярен израз в Rust, добавяме regex кутията към нашия Cargo.toml файл:

[dependencies]
regex = "1.3.9"

И го импортирайте в нашия код:

use regex::Regex;

Ето прост пример за регулярен израз, който ще съответства на низ:

let re = Regex::new(r"hello").unwrap();
assert!(re.is_match("hello"));

Синтаксис на Regex в Rust

Rust поддържа повечето стандартни синтаксиси на регулярни изрази. Няколко примера:

Котви — ^ съответства на началото на низа, $ съвпада с края на низа. Точка — . съвпада с всеки отделен знак. Класове знаци — [abc] съвпада с a, b или c. [^abc] съвпада с всичко освен a, b, c. [a-z] съответства на всяка буква. Повторение, +, ? умножете предишния токен. {n} се повтаря точно n пъти. {n,m} се повтаря от n до m пъти.
Редуване — | съвпада с ляв или десен модел. Ескейпиране — \ екранира специални знаци като
, ., $ и т.н. Групиране — (abc) групира множество токени заедно. Наименувани групи за улавяне — (?P…) дефинира наименувана група за улавяне.

Ето някои примери за тези правила за синтаксис на регулярен израз в Rust:

// Anchors
let re = Regex::new(r"^hello").unwrap(); // Must start with hello
let re = Regex::new(r"hello$").unwrap(); // Must end with hello

// Dot 
let re = Regex::new(r"h.llo").unwrap(); // Matches h+any char+llo

// Character class
let re = Regex::new(r"h[ae]llo").unwrap(); // Matches hallo or hello

// Repetition  
let re = Regex::new(r"ha*").unwrap(); // h followed by 0 or more a
let re = Regex::new(r"ha+").unwrap(); // h followed by 1 or more a
let re = Regex::new(r"ha?").unwrap(); // h followed by 0 or 1 a

// Grouping 
let re = Regex::new(r"(ha){3}").unwrap(); // ha ha ha

Примери за регулярни изрази в Rust

Сега нека да разгледаме някои полезни примери за регулярни изрази в Rust:

Потвърдете имейл

let re = Regex::new(r"^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$").unwrap();
assert!(re.is_match("[email protected]"));
assert!(!re.is_match("hello@example")); // Missing .com

Проверка на URL

let re = Regex::new(r"^https?://[a-z0-9-.]{2,}\.[a-z]{2,4}(:[0-9]{2,5})?/?.*$").unwrap(); 
assert!(re.is_match("https://example.com")); 
assert!(!re.is_match("example.com")); // Missing https

Извличане на хаштагове от Tweet

let text = "Hello #world! This is #awesome. #foo #bar";
let re = Regex::new(r"#([a-z0-9_]+)").unwrap();
for cap in re.captures_iter(text) {
    println!("Hashtag: {}", &cap[1]); 
}
// Prints:
// Hashtag: world 
// Hashtag: awesome 
// Hashtag: foo
// Hashtag: bar

Намерете всички числа в низ

let text = "Hello 123 world! 42 is 10";
let re = Regex::new(r"\d+").unwrap(); // \d means digit
for mat in re.find_iter(text) {
    println!("{}", &text[mat.start()..mat.end()]); 
}
// Prints:
// 123 
// 42
// 10

Замяна на появявания на шаблон

let re = Regex::new(r"\s+").unwrap(); // \s means whitespace
let replaced = re.replace_all("Hello  world!\nHow  are\tyou?", " ");
assert_eq!(replaced, "Hello world! How are you?");

Разделяне на низ върху шаблон

let re = Regex::new(r"\s+").unwrap(); 
let splits = re.split("Hello  world!     How");
assert_eq!(splits.collect::<Vec<&str>>(), &["Hello", "world!", "", "How"]);

Regex на байтови низове срещу Unicode низове

По подразбиране регулярният израз на Rust работи с Unicode низове. За да използвате вместо това върху байтови низове, добавете флага b:

let re = Regex::new(r"[a-z]".as_bytes()).unwrap(); // On bytes
let re = Regex::new(r"(?-u)[a-z]").unwrap(); // Also bytes

Ето пример, в който разграничението е важно:

let unicode_re = Regex::new(r"ça").unwrap();
assert!(unicode_re.is_match("ça va?"));

let byte_re = Regex::new(r"(?-u)ça").unwrap(); 
assert!(!byte_re.is_match("ça va?")); // Fails on byte string

Регулярният израз на Unicode работи, защото низовете на Rust са Unicode по подразбиране. Байтовият регулярен израз е неуспешен, защото „ç“ е два байта, така че моделът не съвпада.

Допълнителни теми

Има още няколко теми за регулярни изрази, които е полезно да знаете в Rust:

  • Ефективност — Компилиране на регулярни изрази по време на изпълнение спрямо време на компилиране с макроси за регулярен израз
  • Итератори — Използване на регулярен израз с итератори за ефективно търсене
  • Набори — Макросът regex_set! за съвпадение на някой от няколко регулярни израза
  • И още! Щайгата regex има много допълнителни функции.

Резюме

Регулярните изрази са мощен инструмент за обработка на низове в Rust. Касата regex предоставя стабилен API за работа с регулярни изрази, поддържащ Unicode низове, байтови низове, набори, макроси и други. Надявам се, че това ръководство ви даде солиден преглед на това как да работите с regex във вашите програми на Rust! Уведомете ме, ако имате други въпроси.