首页 / 教程文章 / 正则贪婪匹配与非贪婪匹配:一次讲透 .* 和 .*? 的区别

正则贪婪匹配与非贪婪匹配:一次讲透 .* 和 .*? 的区别

发布于 2026-08-18 16:00:00 · 2 阅读 · 标签:正则表达式,regex,贪婪匹配,教程

.* 会一口气吃到行尾再回溯,.*? 只吃到最近满足条件的位置。用实例讲清贪婪、懒惰与回溯机制,避免经典匹配错误。

一、默认都是贪婪的

正则里的量词 * + {n,} 默认贪婪:尽可能多地匹配。对字符串 <a>hello</a><a>world</a><.+> 匹配,结果是整个字符串——因为 .+ 一路吃到行尾,再回溯找到最后一个 >

二、加个问号变懒惰

量词后加 ? 就是非贪婪(懒惰):尽可能少匹配。<.+?> 匹配上面同样的字符串,得到两个结果:<a></a>(各自单独),因为它遇到第一个满足条件的 > 就停下。

抓取 HTML 标签内容 <a>(.+?)</a> 时,懒惰模式才能正确分组捕获。

三、回溯:性能杀手

贪婪匹配「先吃过头再吐回来」的过程叫回溯。灾难性例子:对长字符串用 (a+)+b 且字符串末尾没有 b,回溯次数呈指数增长,正则引擎直接卡死——这也就是 ReDoS(正则拒绝服务)攻击的原理。

四、三个实用对照

  1. "(.*)" 贪婪:一行有两个引号对时只匹配一大段;"(.*?)" 懒惰:正确匹配每一对引号。
  2. \d{2,} 匹配 12345 会吃满 5 位;\d{2}? 只匹配 2 位。
  3. 独占模式 .*+(部分语言支持)不回溯,要么全匹配要么失败,可用于锁死性能。

在线体验

不用装任何环境,直接用本站正则在线测试工具在线操作,数据都在浏览器本地处理,方便又安全。

常见问题

.* 和 .*? 到底用哪个?

取决于需求:想匹配到一行中「最后」某个边界用 .*,想匹配「最近」的边界用 .*?。提取成对标签、引号内容时几乎都用懒惰模式。

为什么我的正则把整行都匹配了?

大概率中了贪婪陷阱。检查量词(* + {n,}),在后面加 ? 改成非贪婪试试,或把 . 换成排除字符类 [^x]。

正则能解析 HTML 吗?

简单固定的片段可以,完整 HTML 解析不行(嵌套结构超出了正则能力,属上下文无关文法)。正式场景请用 DOM 解析器,正则只做辅助。

更多文章