用单行替换所有正则表达式匹配

dam*_*mir 26 python regex

我有动态正则表达式,其中我事先不知道它有多少组我想用xml标签替换所有匹配

re.sub("(this).*(string)","this is my string",'<markup>\anygroup</markup>')
>> "<markup>this</markup> is my <markup>string</markup>"
Run Code Online (Sandbox Code Playgroud)

是单线还是可能吗?

Mar*_*nas 33

对于像你的例子那样的常量正则表达式,做

re.sub("(this)(.*)(string)",
       r'<markup>\1</markup>\2<markup>\3</markup>',
       text)
Run Code Online (Sandbox Code Playgroud)

请注意,如果您不想丢失它,则需要在括号中包含.*.

现在,如果你不知道正则表达式是什么样的,那就更难了,但应该是可行的.

pattern = "(this)(.*)(string)"
re.sub(pattern,
       lambda m: ''.join('<markup>%s</markup>' % s if n % 2 == 0
                         else s for n, s in enumerate(m.groups())),
       text)
Run Code Online (Sandbox Code Playgroud)

如果您的模式匹配的第一个东西不一定必须被标记,请使用此代码,第一个组可选地匹配一些应该保留的前缀文本:

pattern = "()(this)(.*)(string)"
re.sub(pattern,
       lambda m: ''.join('<markup>%s</markup>' % s if n % 2 == 1
                         else s for n, s in enumerate(m.groups())),
       text)
Run Code Online (Sandbox Code Playgroud)

你明白了.

如果你的正则表达式很复杂并且你不确定你是否可以将所有东西都放在一个组中,那么只需要标记每一个第二组,你可以用更复杂的函数做更聪明的事情:

pattern = "(this).*(string)"
def replacement(m):
    s = m.group()
    n_groups = len(m.groups())
    # assume groups do not overlap and are listed left-to-right
    for i in range(n_groups, 0, -1):
        lo, hi = m.span(i)
        s = s[:lo] + '<markup>' + s[lo:hi] + '</markup>' + s[hi:]
    return s
re.sub(pattern, replacement, text)
Run Code Online (Sandbox Code Playgroud)

如果你需要处理重叠的组,你可以自己做,但它应该是可行的.


Ign*_*ams 8

re.sub()将取代它所能做的一切.如果你传递一个函数,repl那么你可以做更多.