ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用正则查找 HTML 注释:贪婪与懒惰量词实战(en.javascript.info)

用正则查找 HTML 注释:贪婪与懒惰量词实战(en.javascript.info) 文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载HTML 注释以!--开头、以--结束但注释内容本身可能跨越多行、内部还可能再次出现--子串例如!-- My -- comment。本文以 Modern JavaScript Tutorialen.javascript.info第 9 章《贪婪与懒惰量词》中的配套习题为切入点给出查找 HTML 注释的完整正则方案并从引擎执行机制层面解释为什么不能只用!--.*--以及懒惰量词配合s标志后为什么能正确命中多行注释。习题回顾找出文本中的所有 HTML 注释题目要求见 task.md编写一个正则表达式找出下面文本中的全部 HTML 注释let regexp /your regexp/g; let str ... !-- My -- comment test -- .. !---- .. ; alert( str.match(regexp) ); // !-- My -- comment \n test --, !----期望的匹配结果是两个!-- My -- comment \n test --一条跨越多行的注释注释内容内部还包含--!----一条空内容的短注释。这个例子同时考验两点能否匹配换行符以及能否在注释内容内部出现--的情况下仍然停在正确的位置。标准解法懒惰量词 s标志答案分为两个部分见 solution.md定位注释边界注释一定以!--开始、以--结束因此第一步是找到!--然后匹配其后的所有内容直到--让点号跨行默认情况下点号pattern:.不匹配换行符而 HTML 注释允许跨行必须加上pattern:s标志dotAll让点号匹配包括换行在内的任意字符。可用的完整正则如下let regexp /!--.*?--/gs; let str ... !-- My -- comment test -- .. !---- .. ; alert( str.match(regexp) ); // !-- My -- comment \n test --, !----其中pattern:.*?是关键*?是*的懒惰形式表示尽可能少地重复使点号刚好停在--之前而不会像贪婪的.*那样一路吞到字符串末尾。为什么必须用懒惰量词先看贪婪量词会怎样如果直接写成pattern:/!--.*--/gs贪婪会出现什么问题article.md 用经典的witch and her broom例子说明了贪婪匹配的机制let regexp /./g; let str a witch and her broom is one; alert( str.match(regexp) ); // witch and her broom ← 一个匹配而不是两个引擎在贪婪模式下会这样执行从字符串第 0 位开始逐个位置寻找模式首字符在第 3 位找到接下来匹配pattern:.点号能匹配任意非换行字符引擎尽可能多地吞入字符一直吞到字符串末尾此时模式中剩下的无法匹配字符串已经到头引擎开始回溯backtracking把.的长度一次缩短一个字符再尝试匹配如此反复缩短直到第一个与最后一个配对成功——于是witch and her broom整体成了单个匹配。同理若对 HTML 注释使用贪婪的!--.*--当文本中出现多条注释时.*会把从第一个!--到最后一个--之间的所有内容包括中间的其他注释与文本吞进同一条匹配里产生错误结果。懒惰模式如何修正匹配把?放在量词后面即可切换为懒惰模式见 article.md 的 Lazy mode 一节*?*的懒惰形式?的懒惰形式???自身的懒惰形式。注意单独的?本身是一个量词表示零次或一次但跟在另一个量词或它自己之后时含义变为把匹配模式从贪婪切换为懒惰。懒惰模式的执行逻辑与贪婪正好相反引擎在每次重复量词之前先尝试匹配模式的其余部分只有失败时才增加一次重复如此逐步增加直到成功。对pattern:/.?/g而言结果立即恢复正确let regexp /.?/g; let str a witch and her broom is one; alert( str.match(regexp) ); // witch, broom重要前提懒惰只对紧跟着?的那个量词生效其余量词仍保持贪婪article.md 中的/\d \d?/示例\d贪婪吞下123\d?懒惰只取一个4最终匹配123 4。回到 HTML 注释!--.*?--中懒惰的.*?让引擎每前进一个字符就先尝试匹配--遇到注释内第一个--立即停住。这正是注释内容内部出现--如My -- comment仍能正确匹配的原因——--后面没有引擎不会误停。s标志让点号跨过换行仅靠懒惰量词还不够HTML 注释可以跨越多行而默认的点号不匹配换行符article.md 明确说明 dot 表示 any character except a newline。因此必须给正则加上pattern:s标志即 dotAll 模式let regexp /!--.*?--/gs;g全局搜索找出所有注释而非第一个s使.匹配任意字符包括换行符。如果不加s多行注释!-- My -- comment\n test --将无法匹配这正是原题答案中特别强调Otherwise multiline comments wont be found的原因。备注如果对 dotAll 标志不熟悉也可以用字符类[\s\S]替代点号写成!--[\s\S]*?--同样能覆盖换行但s标志是更简洁、可读性更好的现代写法。更稳妥的备选思路用排除字符类精确化贪婪article.md 在 Alternative approach 一节中强调懒惰并不是万能的有些场景下带排除的精确化贪婪反而更合适。典型例子是查找带classdoc的链接贪婪的a href.* classdoc多条链接会被合并成一条匹配懒惰的a href.*? classdoc遇到a hreflink1 classwrong... p style classdoc时会错误地跨过第一个标签、匹配到后面p里的classdoc而href[^]*直接限定href属性值不含引号无论贪婪与否都能停在最近的引号处两种输入下结果都正确let str1 ...a hreflink1 classwrong... p style classdoc...; let str2 ...a hreflink1 classdoc... a hreflink2 classdoc...; let regexp /a href[^]* classdoc/g; alert( str1.match(regexp) ); // null无匹配正确 alert( str2.match(regexp) ); // a hreflink1 classdoc, a hreflink2 classdoc这条思路对 HTML 注释同样成立注释内容中不允许出现--这一序列HTML 规范中注释结束符就是--内容里出现--是受限的因此也可以写出基于排除的变体。不过在内容里可能合法出现--这类宽松场景下!--.*?--加s标志仍然是首选的简洁解法。同主题延伸练习该章节还配套了两个同主题练习可用于巩固对懒惰量词与 HTML 结构的理解A match for /d? d?/分析123 456.match(/\d? \d?/g)的结果。答案是123 4——第一个懒惰的\d?必须至少取到空格所以是123第二个懒惰的\d?只取一个4就足够见 solution.md。Find HTML tags找出所有带属性的开/闭标签。解法是pattern:[^]——在假设标签属性含引号内不出现和的前提下用排除字符类精确限制标签内容见 solution.mdlet regexp /[^]/g; let str a href/ input typeradio checked b; alert( str.match(regexp) ); // a href/, input typeradio checked, b这两个练习与查找 HTML 注释互为印证懒惰量词解决停在哪里的问题排除字符类解决允许哪些内容的问题二者经常需要搭配使用。总结查找 HTML 注释的核心结论标准解法/!--.*?--/gs其中.*?是懒惰量词s标志让点号匹配换行二者缺一不可。贪婪与懒惰的本质区别贪婪量词尽可能多地重复失败时通过回溯逐步缩短懒惰量词尽可能少地重复先尝试匹配模式的其余部分、失败才逐步增加。相关机制详解见 article.md。懒惰不是银弹当停止条件难以用模式其余部分表达如上面a与p的例子时应改用排除字符类例如[^]、[^]这类精确化的贪婪写法。记住两个实用要点懒惰只对紧随?的量词生效默认点号不跨行需要时用s标志或[\s\S]替代。赞分享文档/教程前端【免费下载链接】en.javascript.infoModern JavaScript Tutorial项目地址https://gitcode.com/gh_mirrors/en/en.javascript.info点击查看免费下载相关推荐JavaScript 正则表达式实战用惰性量词精确匹配 HTML 注释附贪心陷阱解析JavaScript 正则表达式实战用惰性量词精确匹配 HTML 注释附贪心陷阱解析 本篇指南以 JavaScript 教程仓库中的实战任务为线索讲解如文档/教程前端JavaScript正则表达式中的贪婪与懒惰模式详解JavaScript正则表达式中的贪婪与懒惰模式详解 正则表达式是JavaScript中强大的文本处理工具而量词 quantifiers 的使用则是正则表达式文档/教程前端Modern JavaScript Tutorial正则表达式中的贪婪与懒惰量词Greedy and Lazy Quantifiers完全指南Modern JavaScript Tutorial正则表达式中的贪婪与懒惰量词Greedy and Lazy Quantifiers完全指南 导读 在文档/教程前端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表