[英]regex for HTML attributes inside a single opening tag (no child elements)
旁白:这个问题不是RegEx match open tags 除了 XHTML self-contained tags的重复,其答案是“不要对 HTML 使用正则表达式,因为你不能”。 这个答案不是这个问题的解决方案。 这个问题需要一个正则表达式解决方案,我找到了解决方案并将其发布在下面。
这是我想在不使用 DOM API的情况下从中获取属性的 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>
这是我到目前为止的正则表达式:
/(?:\s(?:[^'"/\s><]+?)[\s/>])|(?:\S+(?:\s*=\s*(?:(?:(['"])[\s\S]*?\1|([^\s>]+))|(?:[^'"\s>]+))))/g
它几乎可以工作。 样本:
const re = /(?:\s(?:[^'"/\s><]+?)[\s/>])|(?:\S+(?:\s*=\s*(?:(?:(['"])[\s\S]*?\1|([^\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=() ab=df-b"ar=() ac=df"-bar=() ad=df-bar=() ></div> ` const result = html.match(re).map(s => s.trim()) console.log(result)
在这里现场探索:
https://regexr.com/6p82g或https://regex101.com/r/1zOh1S/1
它没有拾取lorem
布尔属性,并且bar= zxcv
属性被错误地检测为两个属性。
如果删除第一部分(?:\s(?:[^'"/\s><]+?)[\s/>])|
,那么它几乎也可以工作,它会选择除布尔值之外的所有属性属性(不带=
):
https://regexr.com/6p82j或https://regex101.com/r/iLOVpv/1
我们如何才能正确选择所有属性?
[^'"/\s><]
替换为[^/\s><=]
以避免它拾取带有值的属性,并且还拾取名称中带有引号的布尔属性,例如foo"bar
或foo'bar
(这些是完全有效的)[\s/>]
以将其从实际匹配中排除( (?=[\s/>])
),这样我们就解决了背靠背布尔属性(fe lorem
)不存在的问题包括\S+
替换 \ \S+?
这样当我们添加捕获组时,像ad=df-bar=()
这样的属性将被检测为具有值df-bar=()
的名称ad
而不是具有值()
的名称ad=df-bar
|([^'"\s>]+)
,它不做任何事情,并允许我们删除一个非捕获组包装器(保留那些用于表达意图)最终的正则表达式是:
/(?:\s([^/\s><=]+?)(?=[\s/>]))|(?:(\S+?)(?:\s*=\s*(?:(['"])([\s\S]*?)\3|([^\s>]+))))/g
样本:
const re = /(?:\s([^/\s><=]+?)(?=[\s/>]))|(?:(\S+?)(?:\s*=\s*(?:(['"])([\s\S]*?)\3|([^\s>]+))))/g // ^ capture group 1: boolean attribute name (attributes without values) // ^ capture group 2: non-boolean attribute name // ^ capture group 4: non-boolean attribute value with quotes // ^ capture group 5: non-boolean attribute value without quotes 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=() ab=df-b"ar=() ac=df"-bar=() ad=df-bar=() ></div> ` const result = Array.from(html.matchAll(re)) for (let i = 0, l = result.length; i < l; i += 1) { const match = result[i] console.log('name: "' + (match[1] || match[2]) + '", value: "' + (match[4] || match[5] || "") + '"') }
现场探索: https ://regexr.com/6p8p0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.