使用正则表达式保留中间字符串

Retain intermediate string using regex

我想在多个 python 代码文件中的所有出现处将子字符串附加到字符串模式。然而,原始字符串遵循一种模式,并且每次都不是完全相同的字符串。 以下是变化的一些示例:

Original Code:  a.b();
Want Code:      a.b().c();
Original Code:  a.b(param1=1);
Want Code:      a.b(param1=1, param2=2).c();
Original Code:  a.b(param1=1, param2=2);
Want Code:      a.b(param1=1, param2=2).c();
Original Code:  a.b(param1=D());
Want Code:      a.b(param1==D()).c();
Original Code:  X(a.b(param1=D()));
Want Code:      X(a.b(param1==D()).c());

更新: 由于我试图替换文件中的代码,该文件包含缩进和换行以提高可读性: 例如

Original Code:  X(a.b(
                     param1=D()
                     )
                 );

Want Code:      X(a.b(
                     param1=D()
                     ).c()
                 );
Original Code:  X(a.b(
                     param1=D(),
                     param2="qwerty"
                     )
                 );

Want Code:      X(a.b(
                     param1=D(),
                     param2="qwerty"
                     ).c()
                 );
Original Code:  X(a.b(
                       newObj())
                 );

Want Code:      X(a.b(
                       newObj()).c()
                 );

我不太关心函数 b 中传递的参数。我只需要在每次调用 a.b() 时追加调用 c()。

我正在使用正则表达式 'a.b(.*?)' 来检测适当的原始代码。我尝试使用 以下解决方案正则表达式:a.b().c()a.b().c() 但无济于事。

这个怎么样:

模式:(a\.b\(.*?\))

替换:.c()

结果:

a.b(param1=1).c();
a.b(param1=1, param2=2).c();
a.b().c();

https://regex101.com/r/VwxWR3/1/

你可以使用

a\.b\([^()]*\)(?=;)
  • a\.b 按字面匹配并转义点
  • \([^()]*\) 使用否定字符从左括号匹配到右括号 class
  • (?=;) 正面前瞻,向右断言 ;

Regex demo | Python demo

并替换为完整匹配项 \g<0>,然后是 .c()

\g<0>.c()

例如:

import re

regex = r"a\.b\([^()]*\)(?=;)"

s = ("a.b();\n"
    "a.b(param1=1);\n"
    "a.b(param1=1, param2=2);")

result = re.sub(regex, r"\g<0>.c()", s)

if result:
    print (result)

输出

a.b().c();
a.b(param1=1).c();
a.b(param1=1, param2=2).c();

使用 PyPi regex module:

匹配平衡括号
a\.b(\((?>[^()]++|(?1))*\))

模式匹配:

  • a\.b 匹配 .b
  • ( 捕获 组 1
    • \( 匹配 (
    • (?>原子组(无回溯)
      • [^()]++ 匹配除 ()
      • 之外的任何字符出现 1 次以上
      • |
      • (?1) 递归第一个子模式(第 1 组)
    • )* 关闭群组并可选择重复
    • \) 匹配 )
  • ) 关闭组 1

Regex demo | Python demo

import regex

pattern = r'a\.b(\((?>[^()]++|(?1))*\))'
strings = [
    "a.b();",
    "a.b(param1=1);",
    "a.b(param1=1, param2=2);",
    "a.b(param1=d(abc=\"123\"));"
]

for s in strings:
    m = regex.match(pattern, s)
    if m:
        print(f"{m.group()}.c()")

输出

a.b().c()
a.b(param1=1).c()
a.b(param1=1, param2=2).c()
a.b(param1=d(abc="123")).c()