1

我有一个前瞻正则表达式[^a-z0-9%*][a-z0-9%]{3,}(?=[^a-z0-9%*])。在我的测试中,它从中提取 4 个子字符串@@||imasdk.googleapis.com/js/core/bridge*.html

  • |imasdk
  • .googleapis
  • .com
  • /core

我需要用 2 个旧的正则表达式重写它,因为我不能使用前瞻(正则表达式引擎不支持)。我已将其拆分为[^a-z0-9%*][a-z0-9%]{3,}and[^a-z0-9%*]并在匹配后检查子字符串中的每个第一个正则表达式匹配。

出于某种原因,它也提取 /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是由于跟随.而发现的,它是不正确的

4

1 回答 1

1

LOOKAHEAD_REGEX在匹配后的任何位置查找不在范围内的字符,但带有前瞻的原始正则表达式仅在匹配后立即查看单个字符。这就是您的代码找到/bridge而 regex101 没有找到的原因:您的代码.在匹配后看到某处,而 regex101 只看到*.

您可以通过锚定来修复您的代码,LOOKAHEAD_REGEX以便它只会查看第一个字符:^[^a-z0-9%*]

或者,正如@Sven Marnach 所建议的那样,您可以使用与完整表达式匹配的单个正则表达式:[^a-z0-9%*][a-z0-9%]{3,}[^a-z0-9%*],并去除匹配的最后一个字符。

于 2021-03-30T14:28:12.190 回答