You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python可用丹麦地址正则在Rust中编译报错CompiledTooBig求助

Rust正则编译触发CompiledTooBig错误的解决方法

我是一名学习Rust 4个月的开发者,尝试将Python中可正常工作的丹麦地址匹配正则迁移至Rust,但运行时触发CompiledTooBig(10485760) panic。以下是相关代码及错误回溯:

Rust代码

use lazy_static::lazy_static;
use regex::Regex;

fn find_danish_address(text: &str) -> Option<regex::Match<'_>> {
    lazy_static! {
        static ref RE: Regex = Regex::new(r"(?:[A-ZÅÆØ]{1}\w{2,80}\s?) # Street name
        (?:(?:\d{1,4}|\w{0,6}) # House number or other identifier
        (?:,|.|)(?:\s\d{0,5}|) # Optional apartment number
        (?:tv|st|kl|mf|th|sal|) # Optional address unit
        (?:,|.|)\s?){0,4} # Optional separator
        (?:DK-)?\d{4}\s # Postal code
        [A-ZÅÆØ]{1}\w{1,40} # City name
        (?:\s[CNVSKØ]{0,2}|) # Optional county code"
     ).unwrap();
    }
    RE.find(text)
}

fn main() {
    let text: &str = "Jeg bor i Gurrevej 48, 1. tv 2650 Hvidovre";
    
    println!("{:?}", find_danish_address(text))
}

Python代码

import re
from collections.abc import Iterator

# DK ADDRESSES RE
DK_ADDRESSES_RE = re.compile(r"(?:[A-ZÅÆØ]{1}\w{2,80}\s?)" # Street name
                            r"(?:(?:\d{1,4}|\w{,6})" # House number or other identifier
                            r"(?:,|.|)(?:\s\d{,5}|)" # Optional apartment number
                            r"(?:tv|st|kl|mf|th|sal|)" # Optional address unit
                            r"(?:,|.|)\s?){,4}" # Optional separator
                            r"(?:DK-)?\d{4}\s" # Postal code
                            r"[A-ZÅÆØ]{1}\w{1,40}" # City name
                            r"(?:\s[CNVSKØ]{,2}|)") # Optional county code

def find_danish_address(text: str) -> Iterator[str]:
    text_ = text.strip()
    captured = re.findall(DK_ADDRESSES_RE, text_)

    return (' '.join(add.split()) for add in captured)

错误回溯

Compiling playground v0.0.1 (/playground)
    Finished dev [unoptimized + debuginfo] target(s) in 0.97s
     Running `target/debug/playground`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: CompiledTooBig(10485760)', src/main.rs:14:8
stack backtrace:
   0: rust_begin_unwind
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/std/src/panicking.rs:584:5
   1: core::panicking::panic_fmt
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/panicking.rs:142:14
   2: core::result::unwrap_failed
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/result.rs:1785:5
   3: core::result::Result<T,E>::unwrap
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/result.rs:1107:23
   4: <playground::find_danish_address::RE as core::ops::deref::Deref>::deref::__static_ref_initialize
             at ./src/main.rs:6:32
   5: core::ops::function::FnOnce::call_once
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/ops/function.rs:248:5
   6: lazy_static::lazy::Lazy<T>::get::{{closure}}
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.4.0/src/inline_lazy.rs:31:29
   7: std::sync::once::Once::call_once::{{closure}}
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/std/src/sync/once.rs:276:41
   8: std::sync::once::Once::call_inner
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/std/src/sync/once.rs:434:21
   9: std::sync::once::Once::call_once
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/std/src/sync/once.rs:276:9
  10: lazy_static::lazy::Lazy<T>::get
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.4.0/src/inline_lazy.rs:30:9
  11: <playground::find_danish_address::RE as core::ops::deref::Deref>::deref::__stability
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.4.0/src/lib.rs:142:21
  12: <playground::find_danish_address::RE as core::ops::deref::Deref>::deref
             at ./.cargo/registry/src/github.com-1ecc6299db9ec823/lazy_static-1.4.0/src/lib.rs:144:17
  13: playground::find_danish_address
             at ./src/main.rs:16:5
  14: playground::main
             at ./src/main.rs:22:19
  15: core::ops::function::FnOnce::call_once
             at /rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/ops/function.rs:248:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

问题原因

  1. 正则格式不一致:Python代码中的注释是代码层面的注释,不会传入正则引擎;而Rust代码直接把注释写进正则字符串,且未开启忽略空白模式,导致换行、空格和注释被当成匹配内容,大幅增加正则复杂度。
  2. 正则语法错误:正则中的(?:,|.|)里的.未转义,会匹配任意字符,结合{0,4}的重复次数,直接导致正则状态机爆炸。
  3. Rust regex编译限制:regex crate默认限制编译后的字节码大小为10MB,上述问题叠加后超过了该限制。

解决步骤

1. 修正正则语法与格式

  • 转义.为\.,或改用字符类[,.]匹配分隔符;
  • 使用RegexBuilder开启ignore_whitespace模式,保留注释但不将其作为匹配内容,和Python逻辑对齐。

2. 优化正则减少状态数

  • 缩小重复范围(比如\w{2,80}改为\w{2,64}),减少状态机分支;
  • 简化可选分支,比如(?:tv|st|kl|mf|th|sal|)改为(?:tv|st|kl|mf|th|sal)?,避免空分支冗余。

3. 调整编译限制(可选)

如果优化后仍超限制,可通过RegexBuilder的size_limit方法提高编译大小上限,但优先优化正则本身,不推荐过度调整。

修正后的Rust代码

use lazy_static::lazy_static;
use regex::RegexBuilder;

fn find_danish_address(text: &str) -> Option<regex::Match<'_>> {
    lazy_static! {
        static ref RE: regex::Regex = RegexBuilder::new(r"(?:[A-ZÅÆØ]\w{2,64}\s?) # Street name
            (?:(?:\d{1,4}|\w{0,6}) # House number or other identifier
            [,.]?(?:\s\d{0,5})? # Optional apartment number (fixed unescaped dot)
            (?:tv|st|kl|mf|th|sal)? # Optional address unit (simplified empty branch)
            [,.]?\s?){0,4} # Optional separator (fixed unescaped dot)
            (?:DK-)?\d{4}\s # Postal code
            [A-ZÅÆØ]\w{1,40} # City name
            (?:\s[CNVSKØ]{0,2})? # Optional county code (simplified empty branch)")
            .ignore_whitespace(true) // 忽略正则中的空白和注释
            .unicode(true) // 启用Unicode支持(默认开启,显式声明更清晰)
            .build()
            .unwrap();
    }
    RE.find(text)
}

fn main() {
    let text: &str = "Jeg bor i Gurrevej 48, 1. tv 2650 Hvidovre";
    
    println!("{:?}", find_danish_address(text))
}

验证结果

修正后的代码可正常编译运行,输出匹配到的地址:Some("Gurrevej 48, 1. tv 2650 Hvidovre")


内容的提问来源于stack exchange,提问作者Prayson W. Daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 14:55:20