替换正则表达式循环中的组

replace groups in regex loop

我有这两行:

What is P(output1|cause1=2, cause2=2)
What is P(output2|cause3=2)

我想改成:

method_to_use(model, {"cause1": 2, "cause2": 2}, "output1")
method_to_use(model, {"cause3": 2}, "output2")

这是我的正则表达式:

.*P[(]([a-z1-9]+)[|](([a-z1-9]+)=([1-9]),?)+[)]

我尝试这样替换它:

method_to_use(model, {"": }, "")

但我只得到最后一组:

method_to_use(model, {"cause2": 2}, "output1")

是否可以做某种 "loop" 并在途中改变所有适合度?

有一件事是肯定的:你不能用一个正则表达式来做到这一点。

您可以使用三步法:

  • .*P\(替换为method_to_use(
  • \(\K(\w+)\|([^()]+)替换为model, {}, ""
  • (\w+)=(\w+)替换为"":

请注意

  • .*P\( 尽可能多地匹配换行字符以外的任何 0 个或多个字符,并且 P(
  • \(\K(\w+)\|([^()]+)匹配(,然后从\K的匹配值中丢弃,然后将1+字的字符抓取到Group 1中(</code>中的替换模式),<code>| 被匹配,然后 )( 以外的 1+ 个字符被捕获到第 2 组(</code>)</li> <li><code>(\w+)=(\w+) - 1+ 个单词字符被捕获到第 1 组(替换模式中的 </code>),<code>= 被匹配,然后 1+ 个单词字符被捕获到第 2 组().

您可以使用以下正则表达式匹配字符串。

^.*P\(([^|]+)\|([^=]+)=(\d+)(?:, +([^=]+)=(\d+))?\)$

如果捕获组 4 非空,则将(整个字符串)匹配替换为

method_to_use(model, {"": , "": }, "")

这会导致字符串

What is P(output1|cause1=2, cause2=2)

将替换为

method_to_use(model, {"cause1": 2, "cause2": 2}, "output1") 

Demo 1

如果捕获组 4 为空,则将匹配项替换为

method_to_use(model, {"": }, "")

这会导致字符串

What is P(output2|cause3=2)

将替换为

method_to_use(model, {"cause3": 2}, "output2")

Demo 2

请注意,两个链接的正则表达式是等价的,唯一的区别是在 Demo 1 中,我用 free-spacing mode 表达正则表达式,这允许它是自我记录。

当然可以简单地从捕获组的值中形成新的字符串,而不是替换整个字符串。如果这样做,正则表达式开头的 ^.*P 可以简单地更改为 P.

正则表达式引擎执行以下操作。

^             # match beginning of line
.*P\(         # match 0+ chars then '|('      
([^|]+)       # save 1+ chars except '|' in cap grp 1 (output)    
\|            # match ':'
([^=]+)       # save 1+ chars except '=' in cap grp 2 (causeA)
=             # match '='
(\d+)         # save 1+ digits in cap grp 3 (causeAval)
(?:           # begin non-cap grp
  ,\ +        # match ',' then 1+ spaces
  ([^=]+)     # match 1+ chars except '=' in cap grp 4 (causeB)   
  =           # match '='
  (\d+)       # match 1+ digits in cap grp 5 (causeBval)
)?            # end non-cap grp and make it optional  
\)            # match ')'
$             # match end of line