测试正则卡住

异常报告 · 18 次浏览
沉没的白鲸 创建于 3天10小时前

偶然发现输入“一些多行文本”和比较复杂的正则表达式的正则匹配会卡住,而且CPU占用很高。做了这个测试动作,发现中间删掉一些或者开头删一个字都能运行,应该不是零宽字符的原因。

录屏演示见测试动作:测试正则卡住 - by 沉没的白鲸 - 动作信息 - Quicker
https://getquicker.net/Sharedaction?code=5d09702b-7143-40da-9cef-08ddc5acfa0f 

好像不包含\n的文本就不会触发这个问题,目前我的动作在正则模块前面加个$={text}.Trim().Contains("\n")  提前判断,避免用这个正则。

沉没的白鲸 最后更新于 2025/7/19

回复内容
CL 3天5小时前
#1

猜测可能是正则表达式会引起循环判断。

AI的分析:

这个正则表达式可能导致 CPU 100% 的长时间占用,是因为它存在 "灾难性回溯(catastrophic backtracking)" 的风险,特别是在匹配失败的情况下。


✅ 关键原因分析:

正则:

^(?:[a-zA-Z]\:|\\\\[\w\-]+\\[\w\-]+)
(?:\\([^\s\\/:*?\"<>|\x00-\x1F][^\\/:*?\"<>|\x00-\x1F]{0,252}[^\s.\\/:*?\"<>|\x00-\x1F])|([^\s.\\/:*?\"<>|\x00-\x1F]{1,254}))*
(?:\.[^\s.\\/:*?\"<>|\x00-\x1F]{1,254})?$

🧨 可能出现灾难性回溯的部分:

(...)* 

也就是:

(?:\\(...pattern...)|(...pattern...))*

这个重复结构里包含了两个复杂的分支:

  • 每个分支都匹配较长的字符串(最多 254 字符)

  • 而且里面嵌套了重复匹配(比如 {0,252}{1,254}

  • 加上字符类中排除了很多特殊字符,匹配失败时容易出现 大量路径尝试

当你给这个正则提供一个 长但不合法的字符串(特别是路径结构相似,但结尾缺少必要部分的字符串),正则引擎就会:

  • 在重复的 * 中尝试所有可能的拆分方式

  • 对于每种方式再分别尝试两个分支

  • 每个失败都可能回退并重新尝试另一组合

这就可能造成 指数级的回溯路径数量,进而造成 CPU 占用爆满、甚至浏览器或程序卡死


🧪 举个例子:

尝试匹配这样的字符串时:

C:\aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...

如果它最终 没有以合法文件名或扩展名结尾,就会:

  • 重复匹配多个 \a...a 的片段

  • 每一个 \a...a 都进入 (...)* 中的备选分支匹配

  • 匹配失败时尝试所有组合分支重新排列

  • 成千上万的回溯路径引爆 CPU


🔧 如何改进

  1. 避免在重复结构中使用包含备选分支和复杂限定符的结构

    • 将分支拆分成更简单的模式

    • 用非贪婪匹配或限定匹配次数限制路径长度

  2. 使用原子组(如果你的正则引擎支持)

    (?>...) 
    

    表示一旦匹配成功就不再回溯,可以用来包裹重复体。

  3. 事先预处理字符串长度或结构,避免喂给正则一个可能失败的大字符串。


✅ 总结

这个正则式性能问题的核心在于:

在嵌套分支和重复结构中匹配大量复杂字符,失败时触发灾难性回溯。

你可以通过简化正则结构、添加原子组、控制输入长度、使用更安全的正则引擎(如 RE2)等方式进行优化。

如果你愿意,我可以帮你重写这个正则,使其更高效和安全。

沉没的白鲸 回复 CL 3天1小时前 :

感谢。看来确实很危险,以后避免用这种正则了

回复主贴