[英]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.