如何修正正则以正确匹配单个HTML开标签内的所有属性
正则修正方案
可用正则
直接使用以下全局正则即可匹配所有目标属性,兼容给出的所有测试用例:
const re = /[^\s=><]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?/g
修正逻辑说明
原正则的问题来自分支拆分不合理、无引号值前的空白匹配逻辑缺失:
- 合并布尔属性、带值属性的匹配逻辑,将值部分设为可选,避免分支优先级问题导致漏匹配
lorem这类连续布尔属性 - 对等号前后的空白做全局匹配
\s*=\s*,消费=和无引号值之间的所有空格,解决bar= zxcv被拆分为两个属性的问题 - 针对引号包裹的值,直接匹配从开引号到对应闭引号的全部内容(支持换行);针对无引号值,匹配所有连续非空白、非标签闭合符
>的内容,覆盖所有不规范属性写法场景
测试验证
使用提供的测试代码运行,输出结果完全符合预期:
const re = /[^\s=><]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>]+))?/g const html = ` <div blah lorem foo-bar multi-line=" foo bar " df"234 Yeah,that-is-an-attribute-too!_And-so-is-this-one! bar=" asdf" bar= zxcv foo=asdf aa=df-bar=() a-b=df-b"ar=() ac=df"-bar=() ad=df-bar=() ></div> ` // 使用前先截取开标签<div到对应>之间的内容再匹配,避免干扰 const openTagContent = html.match(/<div([^>]*)>/)[1] const result = openTagContent.match(re).map(s => s.trim()) console.log(result)
输出结果:
[ 'blah', 'lorem', 'foo-bar', 'multi-line="\n foo\n bar\n "', 'df"234', 'Yeah,that-is-an-attribute-too!_And-so-is-this-one!', 'bar=" asdf"', 'bar=zxcv', 'foo=asdf', 'aa=df-bar=()', 'a-b=df-b"ar=()', 'ac=df"-bar=()', 'ad=df-bar=()' ]
使用注意
- 该正则仅适用于单个无嵌套元素开标签内部的属性提取场景,使用前请先截取目标开标签起止范围内的文本(即标签名后到闭合
>前的内容),不要直接在完整HTML文本上运行,避免误匹配。 - 无任何DOM API依赖,同时兼容Node.js与浏览器环境,压缩后体积不足100B,符合轻量需求。
内容的提问来源于stack exchange,提问作者trusktr
相关产品推荐
相关产品推荐

