Python复杂正则表达式替换

时间:2013-04-22 18:39:11

标签: python regex replace

我正在尝试做一个简单的VB6到c转换器来帮助我将开源游戏移植到c语言。 我希望能够使用ragex从“使用Npclist [NpcIndex]”获取“NpcList [NpcIndex]”,并将其替换为必须替换的所有位置。 (“With”用作VB6中的宏,在需要时添加Npclist [NpcIndex],直到找到“End With”为止

Example:
 With Npclist[NpcIndex]
 .goTo(245) <-- it should be replaced with Npclist[NpcIndex].goTo(245)
 End With

是否可以使用正则表达式来完成这项工作? 我已经尝试使用一个函数来执行“With”和“End With”之间的另一个正则表达式替换,但我不知道“With”正在替换的文本(Npclist [NpcIndex])。 提前致谢

3 个答案:

答案 0 :(得分:1)

我个人不会相信任何单一的正则表达式解决方案在第一次就做对,也不想调试它。相反,我会逐行解析代码并缓存任何With表达式,以使用它来替换任何直接前面有空格或任何类型括号的.(根据需要添加用例) :

(?<=[\s[({])\. - 来自set + escaped literal dot

的任何字符的正向lookbehind

(?:(?<=[\s[({])|^)\. - 使用此非捕获替代品列表,如果要替换.可以在行的开头

import re

def convert_vb_to_c(vb_code_lines):
    c_code = []
    current_with = ""
    for line in vb_code_lines:
        if re.search(r'^\s*With', line) is not None:
            current_with = line[5:] + "."
            continue
        elif re.search(r'^\s*End With', line) is not None:
            current_with = "{error_outside_with_replacement}"
            continue
        line = re.sub(r'(?<=[\s[({])\.', current_with, line)
        c_code.append(line)
    return "\n".join(c_code)


example = """
With Npclist[NpcIndex]
    .goTo(245)
End With
With hatla
    .matla.tatla[.matla.other] = .matla.other2
    dont.mind.me(.do.mind.me)
    .next()
End With
"""
# use file_object.readlines() in real life
print(convert_vb_to_c(example.split("\n")))

答案 1 :(得分:0)

您可以将函数传递给sub方法:

# just to give the idea of the regex
regex = re.compile(r'''With (.+)
(the-regex-for-the-VB-expression)+?
End With''')

def repl(match):
    beginning = match.group(1)  # NpcList[NpcIndex] in your example
    return ''.join(beginning + line for line in match.group(2).splitlines())

re.sub(regex, repl, the_string)

repl中,您可以从match对象获取有关匹配的所有信息,构建您想要的任何字符串并将其返回。匹配的字符串将被您返回的字符串替换。

请注意,您必须非常小心地编写上面的regex。特别是使用(.+),因为我确实匹配排除换行的所有行,这可能不是你想要的(但我不知道VB,我不知道哪个正则表达式可以去那里而不是捕获只有你想要的。

(the-regex-forthe-VB-expression)+同样如此。我不知道那些代码中可能有哪些代码,因此我向您介绍实现它的细节。 也许占用所有线路都可以,但我不相信这么简单(可能表达式可以跨越多行,对吧?)。

一般来说,在一个大的正则表达式中执行所有操作都会出错并且速度慢。

我强烈考虑使用正则表达式来查找WithEnd With,并使用其他内容来替换。

答案 2 :(得分:0)

这可能会在Python 2.7中实现您所需的功能。我假设您要删除WithEnd With,对吗?你不需要C语言。

>>> import re
>>> search_text = """
... With Np1clist[Npc1Index]
...  .comeFrom(543)
... End With
...
... With Npc2list[Npc2Index]
...  .goTo(245)
... End With"""
>>>
>>> def f(m):
...     return '{0}{1}({2})'.format(m.group(1), m.group(2), m.group(3))
...
>>> regex = r'With\s+([^\s]*)\s*(\.[^(]+)\(([^)]+)\)[^\n]*\nEnd With'
>>> print re.sub(regex, f, search_text)

Np1clist[Npc1Index].comeFrom(543)

Npc2list[Npc2Index].goTo(245)