您的第一个正则表达式确实匹配嵌套括号(但不匹配转义括号)。这是可取的吗?
没有嵌套或转义,这些变得简单得多。
这是忽略嵌套可能性的第一个正则表达式的变体:
counter\([^)]*\)
它匹配一个文字counter(,然后是零个或多个非右括号,最后是一个右括号。 (your first regex 和 my simpler version 在 regex101 的完整解释。)
我相信这回答了您的第一个问题,但如果您实际上是在寻找“匹配 [a] 单括号的正则表达式”,那就是 [()],它将匹配左括号或右括号字符。如果您知道要匹配哪一个,也可以显式匹配 \( 或 \)。
匹配引号(不考虑嵌套或转义引号)同样简单:
"[^"]*"
这匹配一个文字双引号字符 ("),然后是零个或多个非双引号字符,然后是另一个文字双引号字符。
您的第二个请求是“单个正则表达式,它将按给定顺序匹配计数器、属性、url 和字符串内容(顺序很重要,因为我想稍后用评估值替换它们)。”
我不确定你打算如何获得 CSS content property 的值,因为它通常在 ::after 或 ::before 伪类中,它们是 not available from the DOM,但这里有一些填充的虚拟代码以便我们可以操纵它:
var css = `content: counter(item)" " attr(data) "" counter(item1,decimal) url('test.jpeg') "hi" attr(xyz); color:red;`;
// harvest last `content` property (this is tricked by `content: "content: blah"`)
var content = css.match(/.*\bcontent:\s*([^;"']*(?:"[^"]*"[^;"']*|'[^']*'[^;"']*)*)/);
if (content) {
var part_re = /(?:"([^"]*)"|'([^']*)'|(?:counter|attr|url)\(([^)]*)\))/g;
while ( part = part_re.exec(content[1]) ) { // parse on just the value
if (part[0].match(/^"/)) { /* do stuff to part[1] */ }
else if (part[0].match(/^'/)) { /* do stuff to part[2] */ }
else if (part[0].match(/^counter/)) { /* do stuff to part[3] */ }
else if (part[0].match(/^attr/)) { /* do stuff to part[3] */ }
else if (part[0].match(/^url/)) { /* do stuff to part[3] */ }
// silently skips other values, like `open-quote` or `counters(name, string)`
}
}
第一个正则表达式(第 4 行)从 CSS 中提取最后一个 content 属性(最后一个是因为它会覆盖以前的实例,但请注意这会愚蠢地从 content: "content: blah" 中提取 content: blah)。在找到分词符的最后一个实例,然后找到content: 之后,它会吸收所有空格,然后匹配行的其余部分,直到分号、双引号或单引号。非捕获组允许双引号或单引号之间的任何内容,这与我们在此答案顶部附近匹配引号的方式非常相似。 (this CSS content regex 在 regex101 的完整解释。)
第二个正则表达式(第 7 行,分配给 part_re)处于一个 while 循环中,因此我们可以按顺序处理 content 属性中的每个单独值。它匹配双引号字符串或单引号字符串或某些命名值(计数器或 attr 或 url)。有关值数据的存储位置,请参见条件和 cmets。在 regex101 对this value parsing regex 的完整解释(请参阅右列中间的“匹配信息”以了解我如何存储值的数据)。