首页 > 解决方案 > 使用正则表达式解析 css 背景 url 和选择器

问题描述

我正在尝试更改具有内联样式的 HTML 页面,我想制作一个捕获背景 url 和选择器的正则表达式,例如:

<div>some html here</div>
<style>#some-selector {
  padding-top: 408px;
}
#some-selector .bg {
  background-image: url(www.some-url.com/some-image.jpg);
}
#some-selector {
  background-position: 43% 97%;
}

我想在这里捕捉的是#some-selector .bgand www.some-url.com/some-image.jpg,记住 HTML 页面很大,表达应该很快

我想出了这个 expr<style[\s\S]*?[>}\/\n](.*){[\s\S]*?background.*?url\((.*?)\)但它不能正常工作,我知道我第一个[\s\S]应该是贪婪的,但是当我删除?它时,它会导致灾难性的回溯<style[\s\S]*[>}\/\n](.*){[\s\S]*?background.*?url\((.*?)\),它确实适用于小字符串,但在整个页面上它会导致灾难性的回溯,我已经使用 regex101 对其进行测试。

任何帮助表示赞赏

编辑:这是一个例子https://regex101.com/r/ZMxOSz/1

标签: regexregex-greedy

解决方案


更新
仔细研究后,我提供了 2 个解决方案,可以在一定程度上减轻回溯问题。
在查看它们之前,我想指出只有极少数与 CSS 语法相关的定界符。
此外,它与定义 CSS 语法的允许字符的顺序和内容更相关。

回溯的解决方法是将正则表达式引擎限制为更少的
可匹配字符并符合战略位置。
如果您查看此处的 CSS 规范 -> https://www.w3.org/TR/CSS21/syndata.html
,您会注意到它完全由正则表达式定义。
这表明 CSS 解析器完全是用正则表达式的切分版本构建的。

然而,虽然将它放入一个
包罗万象的正则表达式中会是一个有趣的练习,但我会拒绝这个挑战,因为
它对我来说没有任何意义。

相反,我会根据您的要求提供这 2 个正则表达式。

第一个:

  • 仅匹配元素中的第一个url()<style>

<style[^>]*?>(?:[^{}:]*{[^{}]*?:[^{}()]*?})*?(?:([^{}:]*){[^{}]*?:\s*url\s*\(\s*([^{}()]*?)\s*\)\s*})

见-> https://regex101.com/r/2SNIks/1


第二个:

  • url()将所有块与<style>元素匹配

(?:<style[^>]*?>|(?!^)\G)(?:(?:(?!</style)[^{}:])*{[^{}]*?:[^{}()]*?})*?(?:([^{}:]*){[^{}]*?:\s*url\s*\(\s*([^{}()]*?)\s*\)\s*})

见-> https://regex101.com/r/d8q6LH/1


对于这两个正则表达式,

  • 选择器在第 1 组中
  • 该网址在第 2 组中

推荐阅读