gpt4 book ai didi

regex - 如何使用共享反向引用进行多次替换?

转载 作者:行者123 更新时间:2023-12-02 04:30:42 25 4
gpt4 key购买 nike

我需要为数据加载兼容性做一些数据转换。嵌套的键:值对需要被展平,并将它们的组 ID 放在每个子数据的前面。

我一直在尝试理解页面 Repeating a Capturing Group vs. Capturing a Repeated Group但我似乎无法理解它。

到目前为止我的表情:

"(?'group'[\w]+)": {\n((\s*"(?'key'[^"]+)": "(?'value'[^"]+)"(?:,\n)?)+)\n},?

工作样本:https://regex101.com/r/Wobej7/1

我知道使用 1 个或多个中间步骤会简化流程,但此时我想知道这是否可能。

源数据示例:

"g1": {
"k1": "v1",
"k2": "v2",
"k3": "v3"
},
"g2": {
"k4": "v4",
"k5": "v5",
"k6": "v6"
},
"g3": {
"k7": "v7",
"k8": "v8",
"k9": "v9"
}

所需的转换:

{"g1","k1","v1"},
{"g1","k2","v2"},
{"g1","k3","v3"},
{"g2","k4","v4"},
{"g2","k5","v5"},
{"g2","k6","v6"},
{"g3","k7","v7"},
{"g3","k8","v8"},
{"g3","k9","v9"}

最佳答案

TL;博士

第一步

搜索:

("[^"]+"):\s*{[^}]*},?\K

替换为\1

Live demo

第 2 步

搜索:

(?:"[^"]+":\s*{|\G(?!\A))\s*("[^"]+"):\s*((?1))(?=[^}]*},?((?1)))(?|(,)|\s*}(,?).*\R*)

替换为:

{\3,\1,\2}\4\n

Live demo

整体理念

由于不同的原因,这不会是单行正则表达式解决方案。最重要的是我们既不能存储匹配的一部分以供以后引用,也不能在 PCRE 中进行无限后视。但幸运的是,大多数类似的问题都可以分两步完成。

第一步应该是将组名移动到 {...} block 的末尾。这样,每次我们想要将匹配项转换为单行输出时,我们都可以获得组名。

("[^"]+"):\s*{[^}]*},?\K
  • ( 捕获组 #1 开始
    • [^"]+"匹配组名
  • ) CG #1 结束
  • :\s*{ 组名应该在一堆其他字符之前
  • [^}]*},? 我们必须继续前进到 block 的末尾
  • \K 丢弃目前所有匹配的东西

我们的组名保存在第一个捕获组中,必须用它替换整个匹配:

\1

现在是这样的 block :

"g1": {
.
.
.
},

看起来像这样:

"g1": {
.
.
.
},"g1"

下一步是匹配每个 block 的键值对,并在 block 末尾捕获最近添加的组名。

(?:"[^"]+":\s*{|\G(?!\A))\s*("[^"]+"):\s*((?1))(?=[^}]*},?((?1)))(?|(,)|\s*}(,?).*\R*)
  • (?: 非捕获组的开始
    • [^"]+"尝试匹配一个组名
    • :\s*{ 组名应该在一堆其他字符之后
    • | 或者
    • \G(?!\A) 从上一场比赛继续
  • ) NCG 结束
  • \s*("[^"]+"):\s*((?1)) 然后尝试匹配并捕获一个键值对
  • (?=[^}]*},?((?1))) 同时匹配并捕获 block 末尾的组名
  • (?|(,)|\s*}(,?).*\R*) 匹配逗号、大括号或换行符等剩余字符

这样,在正则表达式引擎的每次成功尝试中,我们都有四个捕获的数据,它们的顺序是关键:

{\3,\1,\2}\4\n
  • \3 组名(在 block 末尾添加的那个)
  • \1
  • \2
  • \4 逗号(可能有也可能没有)

关于regex - 如何使用共享反向引用进行多次替换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49212631/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com