繁体   English   中英

单个开始标记内的 HTML 属性的正则表达式(无子元素)

[英]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/6p82ghttps://regex101.com/r/1zOh1S/1

它没有拾取lorem布尔属性,并且bar= zxcv属性被错误地检测为两个属性。

如果删除第一部分(?:\s(?:[^'"/\s><]+?)[\s/>])| ,那么它几乎也可以工作,它会选择除布尔值之外的所有属性属性(不带= ):
https://regexr.com/6p82jhttps://regex101.com/r/iLOVpv/1

我们如何才能正确选择所有属性?

  • 将第一个[^'"/\s><]替换为[^/\s><=]以避免它拾取带有值的属性,并且还拾取名称中带有引号的布尔属性,例如foo"barfoo'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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM