Rust正则表达式库pcre2的使用,高性能PCRE2绑定实现复杂文本匹配与模式搜索
Rust正则表达式库pcre2的使用,高性能PCRE2绑定实现复杂文本匹配与模式搜索
pcre2是一个高级的Rust封装库,用于PCRE2(Perl兼容正则表达式2)库。
安装
在项目目录中运行以下Cargo命令:
cargo add pcre2
或者在Cargo.toml中添加:
pcre2 = "0.2.9"
使用示例
以下是一个完整的Rust示例,展示如何使用pcre2库进行正则表达式匹配:
use pcre2::bytes::Regex;
fn main() {
// 编译正则表达式
let re = Regex::new(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})").unwrap();
// 要匹配的文本
let text = b"Today is 2023-04-15, tomorrow is 2023-04-16";
// 查找所有匹配项
for result in re.captures_iter(text) {
let caps = result.unwrap();
// 获取命名捕获组
println!("Year: {}", String::from_utf8_lossy(caps.name("year").unwrap().as_bytes()));
println!("Month: {}", String::from_utf8_lossy(caps.name("month").unwrap().as_bytes()));
println!("Day: {}", String::from_utf8_lossy(caps.name("day").unwrap().as_bytes()));
println!("---");
}
// 替换文本
let replaced = re.replace_all(text, b"$month/$day/$year");
println!("Replaced: {}", String::from_utf8_lossy(&replaced));
}
高级功能示例
use pcre2::bytes::{Regex, RegexBuilder};
fn main() {
// 使用构建器配置正则表达式
let re = RegexBuilder::new()
.caseless(true) // 不区分大小写
.dotall(true) // .匹配所有字符包括换行符
.build(r"^hello.*world$")
.unwrap();
let text = b"HELLO\nRust\nWORLD";
if re.is_match(text).unwrap() {
println!("Pattern matched!");
}
// 使用JIT编译加速匹配
let re = RegexBuilder::new()
.jit(true)
.build(r"\b\w{5}\b") // 匹配5字母单词
.unwrap();
let text = b"The quick brown fox jumps over the lazy dog";
let count = re.find_iter(text).count();
println!("Found {} five-letter words", count);
}
完整示例demo
以下是一个结合基本使用和高级功能的完整示例:
use pcre2::bytes::{Regex, RegexBuilder};
fn main() {
// 示例1:基本日期匹配和替换
println!("=== 基本日期匹配示例 ===");
let date_re = Regex::new(r"(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})").unwrap();
let text = b"Dates: 2023-04-15, 2023-04-16, 2023-04-17";
for cap in date_re.captures_iter(text) {
let caps = cap.unwrap();
println!("完整匹配: {}", String::from_utf8_lossy(caps.get(0).unwrap().as_bytes()));
println!("年-月-日: {}-{}-{}",
String::from_utf8_lossy(caps.name("year").unwrap().as_bytes()),
String::from_utf8_lossy(caps.name("month").unwrap().as_bytes()),
String::from_utf8_lossy(caps.name("day").unwrap().as_bytes()));
}
let replaced = date_re.replace_all(text, b"$day/$month/$year");
println!("替换后文本: {}", String::from_utf8_lossy(&replaced));
// 示例2:高级匹配选项
println!("\n=== 高级匹配选项示例 ===");
let advanced_re = RegexBuilder::new()
.caseless(true)
.multi_line(true)
.build(r"^hello.*world$")
.unwrap();
let multiline_text = b"HELLO\nThis is a test\nWORLD";
if advanced_re.is_match(multiline_text).unwrap() {
println!("多行匹配成功!");
}
// 示例3:JIT加速匹配
println!("\n=== JIT加速匹配示例 ===");
let jit_re = RegexBuilder::new()
.jit(true)
.build(r"\b[a-zA-Z]{5}\b") // 匹配5字母单词
.unwrap();
let sample_text = b"The quick brown fox jumps over the lazy dog";
let matches: Vec<_> = jit_re.find_iter(sample_text).collect();
println!("找到 {} 个5字母单词:", matches.len());
for m in matches {
println!("- {}", String::from_utf8_lossy(&sample_text[m.unwrap().range()]));
}
}
注意事项
目前这个库是PCRE2的一个相对轻量级的封装层,还没有完全覆盖PCRE2的所有功能。没有具体的计划来进一步扩展这个封装,但欢迎提交PR来使更多的PCRE2功能可用。
许可证
双重许可:MIT或UNLICENSE
1 回复
Rust正则表达式库pcre2的使用指南
概述
pcre2
是Rust中一个高性能的PCRE2绑定库,提供了Perl兼容正则表达式的强大功能。相比Rust标准库中的regex
,pcre2
支持更多高级特性,如回溯引用、条件子模式等,适合需要复杂模式匹配的场景。
安装
在Cargo.toml
中添加依赖:
[dependencies]
pcre2 = "0.2"
基本用法
简单匹配
use pcre2::bytes::Regex;
fn main() {
// 创建匹配日期格式的正则表达式
let re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
let text = "Today is 2023-04-15";
// 检查文本中是否包含匹配项
if re.is_match(text.as_bytes()).unwrap() {
println!("Found a date!");
}
}
提取匹配项
use pcre2::bytes::Regex;
fn main() {
// 创建带捕获组的正则表达式
let re = Regex::new(r"(\d{4})-(\d{2})-(\d{2})").unwrap();
let text = "Dates: 2023-04-15, 2022-12-31";
// 遍历所有匹配项
let matches = re.captures_iter(text.as_bytes());
for mat in matches {
let mat = mat.unwrap();
println!("Full match: {}", String::from_utf8_lossy(mat.get(0).unwrap()));
println!("Year: {}", String::from_utf8_lossy(mat.get(1).unwrap()));
println!("Month: {}", String::from_utf8_lossy(mat.get(2).unwrap()));
println!("Day: {}", String::from_utf8_lossy(mat.get(3).unwrap()));
}
}
高级特性
命名捕获组
use pcre2::bytes::Regex;
fn main() {
// 使用命名捕获组的正则表达式
let re = Regex::new(r"(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})").unwrap();
let text = "Date: 2023-04-15";
// 获取命名捕获组
let caps = re.captures(text.as_bytes()).unwrap().unwrap();
println!("Year: {}", String::from_utf8_lossy(caps.name("year").unwrap()));
println!("Month: {}", String::from_utf8_lossy(caps.name("month").unwrap()));
println!("Day: {}", String::from_utf8_lossy(caps.name("day").unwrap()));
}
替换文本
use pcre2::bytes::Regex;
fn main() {
// 创建匹配日期格式的正则表达式
let re = Regex::new(r"(\d{2})/(\d{2})/(\d{4})").unwrap();
let text = "Date: 04/15/2023";
// 替换日期格式
let result = re.replace(text.as_bytes(), &b"$3-$1-$2"[..]).unwrap();
println!("{}", String::from_utf8_lossy(&result));
// 输出: Date: 2023-04-15
}
性能优化
对于需要重复使用的正则表达式,可以编译后复用:
use pcre2::bytes::Regex;
// 使用lazy_static全局缓存正则表达式
lazy_static::lazy_static! {
static ref DATE_RE: Regex = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
}
fn main() {
let text = "Today is 2023-04-15";
if DATE_RE.is_match(text.as_bytes()).unwrap() {
println!("Found a date!");
}
}
完整示例
下面是一个综合使用pcre2各种功能的完整示例:
use pcre2::bytes::Regex;
use lazy_static::lazy_static;
// 预编译正则表达式
lazy_static! {
// 匹配电子邮件地址
static ref EMAIL_RE: Regex = Regex::new(
r"(?x)
^[a-zA-Z0-9._%+-]+ # 用户名
@ # @符号
[a-zA-Z0-9.-]+ # 域名
\.[a-zA-Z]{2,}$ # 顶级域名
"
).unwrap();
// 匹配并提取URL各部分
static ref URL_RE: Regex = Regex::new(
r"(?x)
^
(?<scheme>https?|ftp):// # 协议
(?<host>[^/\s]+) # 主机名
(?:/(?<path>[^\s]*))? # 路径(可选)
$"
).unwrap();
}
fn main() {
// 1. 简单匹配示例
let date_re = Regex::new(r"\d{4}-\d{2}-\d{2}").unwrap();
let text = "Event date: 2023-12-25";
println!("Contains date: {}", date_re.is_match(text.as_bytes()).unwrap());
// 2. 提取匹配项示例
let phone_re = Regex::new(r"(\d{3})-(\d{3})-(\d{4})").unwrap();
let contact = "Phone: 123-456-7890, Fax: 987-654-3210";
for cap in phone_re.captures_iter(contact.as_bytes()) {
let cap = cap.unwrap();
println!("Phone: {}-{}-{}",
String::from_utf8_lossy(cap.get(1).unwrap()),
String::from_utf8_lossy(cap.get(2).unwrap()),
String::from_utf8_lossy(cap.get(3).unwrap()));
}
// 3. 命名捕获组示例
let log_re = Regex::new(
r"\[(?<time>\d{2}:\d{2}:\d{2})\] \[(?<level>\w+)\] (?<message>.+)"
).unwrap();
let log_entry = "[14:30:22] [ERROR] Connection timeout";
if let Some(caps) = log_re.captures(log_entry.as_bytes()).unwrap() {
println!(
"Log - Time: {}, Level: {}, Message: {}",
String::from_utf8_lossy(caps.name("time").unwrap()),
String::from_utf8_lossy(caps.name("level").unwrap()),
String::from_utf8_lossy(caps.name("message").unwrap())
);
}
// 4. 替换文本示例
let reorder_re = Regex::new(r"(\w+), (\w+)").unwrap();
let names = "Smith, John\nDoe, Jane";
let result = reorder_re.replace_all(names.as_bytes(), &b"$2 $1"[..]).unwrap();
println!("Reordered names:\n{}", String::from_utf8_lossy(&result));
// 5. 使用预编译的正则表达式
println!("Is 'test@example.com' valid: {}",
EMAIL_RE.is_match(b"test@example.com").unwrap());
if let Some(caps) = URL_RE.captures(b"https://www.example.com/path/to/page").unwrap() {
println!(
"URL - Scheme: {}, Host: {}, Path: {}",
String::from_utf8_lossy(caps.name("scheme").unwrap()),
String::from_utf8_lossy(caps.name("host").unwrap()),
String::from_utf8_lossy(caps.name("path").unwrap_or_default())
);
}
}
注意事项
- PCRE2支持比Rust标准库regex更多的特性,但也可能带来更大的二进制体积
- 复杂正则表达式可能导致性能下降,特别是使用回溯引用时
- 默认情况下,pcre2使用UTF-8检查,可以通过Builder禁用以提高性能