Rust正则匹配单数字(含单词形式):重叠字符匹配问题求助
解决Rust regex中重叠数字单词的匹配问题
你的问题出在普通正则的贪婪匹配特性:当遇到eightwo这类重叠字符串时,正则会优先匹配更长的eight,匹配完成后消耗掉对应的字符,剩下的wo无法触发two的匹配。要解决这个问题,有两种可行方案:
方案一:使用正向预查的正则表达式
Rust的regex库支持正向预查(零宽度断言),它不会消耗匹配到的字符,能让正则在同一个位置多次检查不同的匹配模式。修改后的正则如下:
let re = Regex::new(r"(?=([0-9]|one|two|three|four|five|six|seven|eight|nine|ten))").unwrap();
原理说明
(?=...)是正向预查断言,它仅验证当前位置后方是否存在匹配的模式,但不会移动正则的匹配指针。这样遍历字符串时,每个字符位置都会被检查是否能匹配数字或数字单词,自然就能捕获到eightwo中的eight和two。
提取匹配结果
需要遍历所有捕获组的内容(预查内的括号是捕获组):
let input = "eightwo"; for cap in re.captures_iter(input) { if let Some(match_str) = cap.get(1) { println!("匹配到: {}", match_str.as_str()); } }
运行后会输出:
匹配到: eight 匹配到: two
方案二:手动遍历字符串(非正则方案)
如果觉得正则的写法不够直观,也可以通过滑动窗口遍历字符串,逐个位置检查匹配情况,逻辑更清晰:
fn extract_all_digits(s: &str) -> Vec<&str> { let digit_words = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"]; let mut results = Vec::new(); let chars: Vec<char> = s.chars().collect(); let mut idx = 0; while idx < chars.len() { // 检查当前字符是否是数字 if chars[idx].is_ascii_digit() { results.push(&s[idx..idx+1]); idx += 1; continue; } // 检查当前位置是否匹配某个数字单词 for &word in &digit_words { let word_len = word.len(); if idx + word_len <= chars.len() && &s[idx..idx+word_len] == word { results.push(word); break; } } idx += 1; } results } // 使用示例 fn main() { let test_str = "eightwo"; let digits = extract_all_digits(test_str); println!("所有匹配结果: {:?}", digits); // 输出 ["eight", "two"] }
原理说明
通过逐个位置遍历字符串:
- 先检查当前字符是否是数字,是则直接加入结果;
- 否则检查从当前位置开始是否能匹配任意数字单词,匹配到就加入结果;
- 每次只移动一个字符的位置,确保重叠的字符串能被多次检查。
内容的提问来源于stack exchange,提问作者dsadsadsadas dsadasdasda
相关产品推荐
相关产品推荐

