)
文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载本篇指南以 JavaScript 教程仓库中的实战任务为线索讲解如何用正则表达式一次性找出文本中的全部 HTML 注释!-- ... --。任务表面简单实则暗藏正则引擎贪心匹配与惰性匹配的核心博弈直接套用!--.*--会因点号吃光所有字符而失败正确解法需要惰性量词.*?配合s标志处理多行注释。读完本篇你将掌握贪心/惰性量词的本质差异、回溯机制以及用排除字符类[^...]替代惰性量词的备选思路并能迁移到 HTML 标签、引号字符串等同类解析场景。任务目标从文本中提取所有 HTML 注释关联任务文档 task.md 给出的需求是在一个包含多处注释的字符串中找到全部HTML 注释。HTML 注释的语法特征是以!--开头、以--结束中间可以是任意内容包括换行、甚至--这样的连续短横线。任务给出了预期的输入与输出let regexp /your regexp/g; let str ... !-- My -- comment test -- .. !---- .. ; alert( str.match(regexp) ); // !-- My -- comment \n test --, !----注意两个关键细节第一个注释跨越多行!-- My -- comment与test --之间有一个换行符\n正则表达式必须能跨越换行完成匹配第二个注释是空注释!----是开标记!-- 闭标记--直接相邻的空注释同样需要被匹配出来。对照配套答案 solution.md标准解法是let regexp /!--.*?--/gs; let str ... !-- My -- comment test -- .. !---- .. ; alert( str.match(regexp) ); // !-- My -- comment \n test --, !----这个正则只有两个非常规部件.*?惰性量词和s标志。下面逐一拆解它们为什么缺一不可。第一道坎贪心量词会把注释吃过头直觉上匹配注释最自然的写法是!--.*--找到!--后用点号.吃掉中间内容直到遇到--。但这一写法在本任务中会失败——原因正是 article.md 中反复强调的贪心陷阱。贪心模式能多取就多取默认情况下量词*、、?、{n,m}等都处于贪心模式greedy mode引擎会尽可能多地重复被量化的字符。以.匹配a witch and her broom is one为例引擎找到第一个引号后.会一路吞掉后面所有字符直到字符串末尾此时剩余模式中还有一个引号需要匹配但字符串已经耗尽引擎开始回溯backtracking把.的匹配长度缩短一个字符再试一次不行再缩短一个……直到把最后能匹配引号的位置让出来。最终的结果是witch and her broom被当成一个匹配而非期望的两个独立引号字符串。这正是 article.md 所演示的现象let regexp /./g; let str a witch and her broom is one; alert( str.match(regexp) ); // witch and her broom只有一个匹配在 article.md 中图 witch_greedy3.svg 直观展示了贪心点号一直吃到字符串末尾、图 witch_greedy6.svg 展示了回溯收缩到最后一个引号的过程。把这个陷阱套用到 HTML 注释如果写!--.*--当文本中同时存在多个注释时第一个!--之后的.*会贪心地吞掉一切直到最后一个--才肯停下导致所有注释被合并成一次匹配甚至把注释之间的普通文本也卷进来。这就是为什么不能用贪心写法直接解题。惰性模式少取为妙够用即停与贪心相反在量词后追加一个问号?即可切换为惰性模式lazy mode引擎在每次重复之前先尝试让模式的剩余部分匹配只有失败时才增加一次重复。书写形式包括*?、?、??对?自身而言。article.md 强调?紧跟另一个量词甚至紧跟自身时不再表示零或一而是把该量词从贪心切换为惰性。文中用图 witch_lazy3.svg 展示了惰性点号每次只前进一个字符就停下来试探剩余模式从而在第一个右引号处成功收口。因此!--.*?--的行为是从!--之后逐字符尝试一旦发现当前字符之后紧跟--立即收口——匹配到最近的一个注释结尾而不会越界吞并后续文本。第二道坎点号默认不匹配换行需要s标志只把量词改成惰性还不够。任务中第一个注释内部包含换行符!-- My -- comment test --而正则中的.点号默认匹配除换行符\n以外的任意字符。参见 字符类章节 的说明点号只有在正则带有s标志dotAll时才匹配包括换行在内的任意字符否则遇到换行即告失败。这正是 solution.md 中特别强调的一点需要为点号添加s标志以包含换行符否则多行注释无法被找到。所以最终解法的两个要素缺一不可要素正则写法作用惰性量词.*?让匹配在第一个--处收口避免吞并多个注释s标志/.../gs让.能跨越换行符从而匹配多行注释验证一下完整运行效果let regexp /!--.*?--/gs; let str ... !-- My -- comment test -- .. !---- .. ; alert( str.match(regexp) ); // !-- My -- comment \n test --, !----两条结果分别对应跨行的完整注释注意匹配结果中保留了内部的\n以及紧邻的空注释!----。这个例子还说明惰性量词对空内容同样有效.*?可以重复零次直接让!--与--相邻即完成匹配。备选方案用排除字符类替代惰性量词惰性量词并非解决此类问题的唯一手段。article.md 在替代方案Alternative approach一节中指出可以用排除字符类实现精确到最近的定界符的效果。例如匹配引号字符串时[^]与惰性的.?殊途同归let regexp /[^]/g; let str a witch and her broom is one; alert( str.match(regexp) ); // witch, broom其原理是[^]明确声明引号以外的任意字符引擎吃到下一个引号时自然停止无需回溯。同理如果要避开点号不匹配换行的限制还可以把.换成[\s\S]匹配任意空白或非空白即任意字符let regexp /!--[\s\S]*?--/g; // 等效于 /!--.*?--/gs不过要注意article.md 同时提醒排除字符类的思路并不能完全替代惰性量词。二者是两种不同的工具——惰性量词在内容允许任意字符时好用排除字符类在能明确界定禁止字符集合时更稳。文中的a href... classdoc示例表明即便把.*改成惰性的.*?在面对a hreflink1 classwrong... p style classdoc这类文本时仍会错误地把两个标签之间的内容卷入匹配因为惰性只保证最早满足不保证语义正确。此时正确方案是href[^]*——用排除引号的字符类严格限定 href 属性值杜绝跨标签匹配。延伸练习用同类思路解析 HTML 标签本章节的姊妹任务 find-html-tags-greedy-lazy 任务 要求找出带属性的开闭 HTML 标签其答案 solution.md 正是排除字符类思路的典范应用let regexp /[^]/g; let str a href/ input typeradio checked b; alert( str.match(regexp) ); // a href/, input typeradio checked, b[^]明确排除了和包括引号内的尖括号从而保证每个标签都在第一个处收口。任务说明中给出的前提假设是标签属性内不包含和这恰好说明排除字符类的有效性建立在你能清晰定义禁区集合之上。与之呼应章节内还有一道巩固题 lazy-greedy 任务考察\d? \d?在123 456上的匹配结果答案是123 4。其解析见 solution.md展示了惰性量词被迫扩张的行为——第一个\d?虽然想少取但为了碰到空格不得不取到123第二个\d?则取一个数字4就足够。这道题与 HTML 注释题共同印证了惰性模式的精确语义每次重复前都先检查剩余模式是否已经能匹配。总结处理从文本中提取 HTML 注释这类问题需要同时具备三块知识缺一不可认清贪心陷阱默认量词会吃到最后一个定界符多个注释会被错误合并根源在于回溯机制活用惰性量词*?/?使引擎够用即停!--.*?--能精确收口在最近的--处理换行点号默认不匹配\n多行注释必须加s标志或改用[\s\S]。最终答案!--.*?--配合gs标志即可一次匹配任务中的两个注释。更进一步当你能明确界定禁区时[^...]排除字符类往往比惰性量词更稳健如 HTML 标签的[^]而当内容完全不可预测时惰性量词则是唯一可行的收口手段。二者结合方能从容应对各类定界符包裹内容的解析场景。更多原理性推导贪心回溯的逐步图解、惰性模式的分步执行、[^]与惰性量词的取舍可继续阅读本章正文 Greedy and lazy quantifiers。赞分享文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载相关推荐JavaScript 正则表达式中的贪婪模式与惰性模式详解JavaScript 正则表达式中的贪婪模式与惰性模式详解 正则表达式是 JavaScript 中强大的文本处理工具而量词的使用则是正则表达式的核心概念之一。文档教程前端JavaScript正则表达式中的贪婪与懒惰模式详解JavaScript正则表达式中的贪婪与懒惰模式详解 正则表达式是JavaScript中强大的文本处理工具而量词 quantifiers 的使用则是正则表达式文档/教程前端learn-regex 正则表达式入门实战指南从基础匹配到贪婪与惰性learn regex 正则表达式入门实战指南从基础匹配到贪婪与惰性 正则表达式Regular Expression简称 regex / regexp是教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考