【发布时间】:2021-06-26 07:17:25
【问题描述】:
我有一个前瞻正则表达式[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])。在my test 中,它从@@||imasdk.googleapis.com/js/core/bridge*.html 中提取4 个子字符串:
|imasdk.googleapis.com/core
我需要用 2 个旧正则表达式重写它,因为我不能使用前瞻(正则表达式引擎不支持)。我将其拆分为[^a-z0-9%*][a-z0-9%]{3,} 和[^a-z0-9%*],并在匹配后检查子字符串中的每个第一个正则表达式匹配。
由于某种原因it extracts/bridge 也因为. 未在[^a-z0-9%*] 中列出,而是在/bridge 之后找到。那么前瞻是如何工作的:它必须是完全匹配、substr(find 结果)还是其他任何东西?这是否意味着在这种情况下,每个结束字符都不应来自集合 a-z0-9%*?
在 Rust 中,代码如下所示:
lazy_static! {
// WARNING: the original regex is `"[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])"` but Rust's regex
// does not support look-around, so we have to check it programmatically for the last match
static ref REGEX: Regex = Regex::new(r###"[^a-z0-9%*][a-z0-9%]{3,}"###).unwrap();
static ref LOOKAHEAD_REGEX: Regex = Regex::new(r###"[^a-z0-9%*]"###).unwrap();
}
let pattern_lowercase = pattern.to_lowercase();
let results = REGEX.find_iter(&pattern_lowercase);
for (is_last, each_candidate) in results.identify_last() {
let mut candidate = each_candidate.as_str();
if !is_last {
// have to simulate positive-ahead check programmatically
let ending = &pattern_lowercase[each_candidate.end()..]; // substr after the match
println!("searching in {:?}", ending);
let lookahead_match = LOOKAHEAD_REGEX.find(ending);
if lookahead_match.is_none() {
// did not find anything => look-ahead is NOT positive
println!("NO look-ahead match!");
break;
} else {
println!("found look-ahead match: {:?}", lookahead_match.unwrap().as_str());
}
}
...
测试输出:
"|imasdk":
searching in ".googleapis.com/js/core/bridge*.html"
found look-ahead match: "."
".googleapis":
searching in ".com/js/core/bridge*.html"
found look-ahead match: "."
".com":
searching in "/js/core/bridge*.html"
found look-ahead match: "/"
"/core":
searching in "/bridge*.html"
found look-ahead match: "/"
"/bridge":
searching in "*.html"
found look-ahead match: "."
^在这里你可以看到/bridge是由于关注.而被发现的,不正确。
【问题讨论】:
-
使用
[^a-z0-9%*][a-z0-9%]{3,}[^a-z0-9%*]并去掉匹配的最后一个字符怎么样? -
似乎不等于正向前瞻的意思。我可能是错的,但我将前瞻理解为“1 个字符不在范围内......比赛结束后的任何地方”,在你的情况下,它预计会在比赛结束后立即跟进
-
不,前瞻是“1 个字符不在匹配后的范围内”(否则您的 regex101 测试会找到
/bridge,因为“匹配后结束”中的.)。 -
如果你想保持双正则表达式的方法,你的第二个表达式应该是
^[^a-z0-9%*]。 -
@Jmb 将其转换为答案,我会接受它
标签: regex rust regex-lookarounds positive-lookahead regex-look-ahead