重复捕获一组逗号分隔的键值对

Repeat capturing group of comma seperated key value pairs

我目前正在尝试从 @Apple(kind="Bax", priority=33)

等模式中提取以下内容

我目前使用的是@([^(]*)\(([^\)]*)\)。然后我有 Applekind="Bax", priority=33。在此之后,我在 , 上拆分第 2 组,然后在 = 上拆分,最后删除 "(如果有的话)。

现在这将遍历第二段很多。首先进行正则表达式捕获,然后查找所有 ,,然后每次遍历再次查找 = 等等

因为我这样做了数百万次,有没有办法通过正则表达式遍历来捕获它?我想避免所有分裂。

如何创建 5 个不同的捕获组并相应地使用它们,那么您不需要使用拆分。请尝试使用正则表达式。

^@([^(]*)\(([^=]*)="(.*?)",\s+([^=]*)=([^)]*)\)

Online demo for above regex

解释: 为以上添加详细解释。

^@        ##Matching starting @ here in value.
([^(]*)   ##Creating 1st capturing group which has everything till ( here.
\(        ##Matching literal ( here.
([^=]*)   ##Creating 2nd capturing group which has everything till - here.
="        ##Matching =" here.
(.*?)     ##Creating 3rd capturing group here, which is a lazy match till next match.
",\s+     ##Matching ", followed by spaces 1 or more occurrences.
([^=]*)   ##Creating 4th capturing group which has everything till = here.
=         ##Matching = here.
([^)]*)\) ##Creating 5th capturing group which has everything till ) here, then matching literal ) here.

假设你想允许 key=value 对的数量是任意长度,怎么样:

(?:@|\(|,\s*|="?)(\w+)(?=\(|=|"|,|\))

Demo

所有捕获都在第 1 组中。

  • (?:@|\(|,\s*|="?) 匹配 @(, 之一加上大于 0 的空格, 或 = 加上可选的 ".
  • (\w+) 匹配所需的词并在 Group1 中捕获。
  • (?=\(|=|"|,|\)) 是匹配 ( 之一的正面前瞻断言, =",).

[编辑]

如果双引号括起来的元素可能包含逗号,用单个正则表达式将不容易解析它。 如果可能的话, 它将更难维护。我会将操作分为两个步骤。 假设我们有一个字符串:

@Apple(val="a,b", kind="Bax", priority=33,foo=bar, name="John Doe", lorem=ipsum)

然后使用第一个正则表达式:

^@([^(]+)\(([^)]+)\)

Apple在第1组中捕获,括号中的子字符串为 在第 2 组中捕获。

然后将下一个正则表达式应用于第 2 组:

(?<=")[^"=]+(?=")|[^,=" ]+

现在我们可以得到列表:

['val', 'a,b', 'kind', 'Bax', 'priority', '33', 'foo', 'bar', 'name', 'John Doe', 'lorem', 'ipsum']

Demo of the 2nd regex

另一种选择可能是利用 \G 锚点对括号之间的部分进行迭代匹配,并匹配可变数量的参数。

@后面的值属于第1组,括号中的键和值属于第2组和第3组

(?:@(\w+)\((?=[^()]*\))|\G(?!^))([^\s=]+)=(?|"([^"*"]*)"|([^\s,]+))(?:,\h*)?

模式匹配:

  • (?:非捕获组
    • @(\w+) 匹配@并捕获第1组
    • 中的1+个单词字符
    • \((?=[^()]*\)) 匹配 ( 并断言右端 )
    • |
    • \G(?!^) 断言位置在上一个匹配的末尾,但不是在开始(锚匹配在 2 个位置也可以在字符串的开头)
  • )关群
  • ([^\s=]+)= 捕获 组 2,匹配除 = 或空白字符之外的任何字符,然后匹配 =
  • (?|分支重置组
    • "([^"*"]*)"|([^\s,]+) 捕获 组 3,捕获双引号之间的内容或 1+ 个不带逗号的非空白字符
  • )(?:,\h*)? 关闭分支重置组并可选择匹配逗号和空格

Regex demo

@(\w+)\((\s*\w+="?\w+"?,?)*\)

此正则表达式采用可变数量的参数。然而,正则表达式的一个限制是你应该有一个恒定数量的捕获组:所以你只会捕获最后一个参数。

下面的正则表达式使用有限数量的参数 (2) 和有限数量的捕获组 (3)

@(\w+)\((\s*\w+="?\w+"?,?)(\s*\w+="?\w+"?,?)\) (注意:为了演示,我只是将参数捕获加倍)