跳转到主要内容
模块 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 次尝试后可用的解决方案