重复捕获一组逗号分隔的键值对
Repeat capturing group of comma seperated key value pairs
我目前正在尝试从 @Apple(kind="Bax", priority=33)
等模式中提取以下内容
- 苹果
- [种类, Bax], [优先级, 33]
我目前使用的是@([^(]*)\(([^\)]*)\)
。然后我有 Apple
和 kind="Bax", priority=33
。在此之后,我在 ,
上拆分第 2 组,然后在 =
上拆分,最后删除 "
(如果有的话)。
现在这将遍历第二段很多。首先进行正则表达式捕获,然后查找所有 ,
,然后每次遍历再次查找 =
等等
因为我这样做了数百万次,有没有办法通过正则表达式遍历来捕获它?我想避免所有分裂。
如何创建 5 个不同的捕获组并相应地使用它们,那么您不需要使用拆分。请尝试使用正则表达式。
^@([^(]*)\(([^=]*)="(.*?)",\s+([^=]*)=([^)]*)\)
解释: 为以上添加详细解释。
^@ ##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+)(?=\(|=|"|,|\))
所有捕获都在第 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']
另一种选择可能是利用 \G
锚点对括号之间的部分进行迭代匹配,并匹配可变数量的参数。
@后面的值属于第1组,括号中的键和值属于第2组和第3组
(?:@(\w+)\((?=[^()]*\))|\G(?!^))([^\s=]+)=(?|"([^"*"]*)"|([^\s,]+))(?:,\h*)?
模式匹配:
(?:
非捕获组
@(\w+)
匹配@并捕获第1组 中的1+个单词字符
\((?=[^()]*\))
匹配 (
并断言右端 )
|
或
\G(?!^)
断言位置在上一个匹配的末尾,但不是在开始(锚匹配在 2 个位置也可以在字符串的开头)
)
关群
([^\s=]+)=
捕获 组 2,匹配除 = 或空白字符之外的任何字符,然后匹配 =
(?|
分支重置组
"([^"*"]*)"|([^\s,]+)
捕获 组 3,捕获双引号之间的内容或 1+ 个不带逗号的非空白字符
)(?:,\h*)?
关闭分支重置组并可选择匹配逗号和空格
@(\w+)\((\s*\w+="?\w+"?,?)*\)
此正则表达式采用可变数量的参数。然而,正则表达式的一个限制是你应该有一个恒定数量的捕获组:所以你只会捕获最后一个参数。
下面的正则表达式使用有限数量的参数 (2) 和有限数量的捕获组 (3)
@(\w+)\((\s*\w+="?\w+"?,?)(\s*\w+="?\w+"?,?)\)
(注意:为了演示,我只是将参数捕获加倍)
我目前正在尝试从 @Apple(kind="Bax", priority=33)
- 苹果
- [种类, Bax], [优先级, 33]
我目前使用的是@([^(]*)\(([^\)]*)\)
。然后我有 Apple
和 kind="Bax", priority=33
。在此之后,我在 ,
上拆分第 2 组,然后在 =
上拆分,最后删除 "
(如果有的话)。
现在这将遍历第二段很多。首先进行正则表达式捕获,然后查找所有 ,
,然后每次遍历再次查找 =
等等
因为我这样做了数百万次,有没有办法通过正则表达式遍历来捕获它?我想避免所有分裂。
如何创建 5 个不同的捕获组并相应地使用它们,那么您不需要使用拆分。请尝试使用正则表达式。
^@([^(]*)\(([^=]*)="(.*?)",\s+([^=]*)=([^)]*)\)
解释: 为以上添加详细解释。
^@ ##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+)(?=\(|=|"|,|\))
所有捕获都在第 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']
另一种选择可能是利用 \G
锚点对括号之间的部分进行迭代匹配,并匹配可变数量的参数。
@后面的值属于第1组,括号中的键和值属于第2组和第3组
(?:@(\w+)\((?=[^()]*\))|\G(?!^))([^\s=]+)=(?|"([^"*"]*)"|([^\s,]+))(?:,\h*)?
模式匹配:
(?:
非捕获组@(\w+)
匹配@并捕获第1组 中的1+个单词字符
\((?=[^()]*\))
匹配(
并断言右端)
|
或\G(?!^)
断言位置在上一个匹配的末尾,但不是在开始(锚匹配在 2 个位置也可以在字符串的开头)
)
关群([^\s=]+)=
捕获 组 2,匹配除 = 或空白字符之外的任何字符,然后匹配=
(?|
分支重置组"([^"*"]*)"|([^\s,]+)
捕获 组 3,捕获双引号之间的内容或 1+ 个不带逗号的非空白字符
)(?:,\h*)?
关闭分支重置组并可选择匹配逗号和空格
@(\w+)\((\s*\w+="?\w+"?,?)*\)
此正则表达式采用可变数量的参数。然而,正则表达式的一个限制是你应该有一个恒定数量的捕获组:所以你只会捕获最后一个参数。
下面的正则表达式使用有限数量的参数 (2) 和有限数量的捕获组 (3)
@(\w+)\((\s*\w+="?\w+"?,?)(\s*\w+="?\w+"?,?)\)
(注意:为了演示,我只是将参数捕获加倍)