模块 2 · 第 4 课(共 4)课程中的8/32~12 min
模块课程(4/4)
回溯:概述
当贪婪量词“过度”时,引擎会执行回溯: 它后退一步,尝试另一种配置,然后重试。在简单的图案上 是看不见的;在写得不好的模式上,它可能会变成指数并且 冻结浏览器几秒钟。它是 ReDoS 的根源(常规 表达拒绝服务)。
Code
Pattern: .*\d
Sample: abc123def
Steps:
1. .* consumes everything: "abc123def"
2. \d fails (end of string).
3. Backtrack: .* drops 'f' -> "abc123de", \d fails on 'f'.
4. Backtrack: .* drops 'ef' -> "abc123d", \d fails on 'e'.
5. ... and so on until \d finds a digit: match = "abc123" + "?"... actually
the pattern matches "abc123" because .* leaves "def" and \d looks at '3'? No: the
backtrack continues and .* ends up being "abc12", \d=3. Final match: "abc123".引擎总是能到达那里,但是如果贪婪量词包含
另一个贪婪量词(例如(a+)+),配置数量
尝试可能会爆炸。
灾难性模式
Code
Pattern: (a+)+b
Sample: aaaaaaaaaaaaaaaaaaaaa没有尾随 b → 模式失败,但为了到达那里,引擎会尝试每一个
a 的可能分区。 指数增长:通过 30 个 a,您可以
等待几个小时。
回溯和 ReDoS 的危险
当模式包含重叠或嵌套量词(例如 (a+)+)时,引擎会在失败之前评估指数数量的路径。用排除字符类替换通用通配符可显着减少回溯路径。
尝试一下
锻炼#regex.m2.l4.e1
尝试:0加载中...
提取文本中每次出现的方括号之间的内容。使用量词的惰性版本以避免跳转到稍后的结束语。
正在加载编辑器...
显示提示
\\[.*?\\] 在第一次结束时停止]:没有大量回溯。
3 次尝试后可用的解决方案
复习练习
锻炼#regex.m2.l4.e2
尝试:0加载中...
查找文本中的每个“http://...”或“https://...” URL,使用“?”量词表示可选的“s”,使用“\\S+”表示路径的非空格字符。
正在加载编辑器...
显示提示
https?表示“http”后跟可选的“s”。然后是//,然后是\\S+(非空格)。
3 次尝试后可用的解决方案
额外的挑战
锻炼#regex.m2.l4.e3
尝试:0加载中...
Match strings enclosed in double quotes, avoiding excessive backtracking by using the negated class `[^"]*` instead of `.*`.
正在加载编辑器...
显示提示
Replace the dot with the negated class [^"] to restrict the engine's backtracking paths.
3 次尝试后可用的解决方案