仅在正则表达式中过滤元素

时间:2018-11-08 17:03:09

标签: python regex string

在一个字符串中(实际上更大):

s = """
BeginA
Qwerty
Element 11 35
EndA

BeginB
Element 12 38
...
Element 198 38
EndB

BeginA
Element 81132 38
SomethingElse
EndA

BeginB
Element 12 39
Element 198 38
EndB
"""

如何用Element <anythinghere> 38替换BeginB...EndB块内的所有Element ABC(只有那些!)?

我正在尝试:

s = re.sub(r'Element .* 38', 'Element ABC', s)

,但这不会检测它是否位于BeginB...EndB块中。该怎么做?

2 个答案:

答案 0 :(得分:2)

尝试以下操作:

r'(?s)(?<=BeginB)\s+Element\s+(\d+)\s+\d+.*?(?=EndB)'

您可以here对其进行测试。

对于您的示例,我将回显@Jan的答案并使用两个单独的正则表达式:

import re

restrict = re.compile(r'(?s)(?<=BeginB).*?(?=EndB)')
pattern = re.compile(r'Element\s+(\d+)\s+38')

def repl(block):

    return pattern.sub('Element ABC', block.group(0))

out = restrict.sub(repl, s)

答案 1 :(得分:2)

使用两个表达式:

block = re.compile(r'BeginB[\s\S]+?EndB')
element = re.compile(r'Element.*?\b38\b')

def repl(match):
    return element.sub('Element ABC', match.group(0))

nstring = block.sub(repl, string)
print(nstring)

这产生

BeginA
Qwerty
Element 11 35
EndA

BeginB
Element ABC
...
Element ABC
EndB

BeginA
Element 81132 38
SomethingElse
EndA

BeginB
Element 12 39
Element ABC
EndB

请参见a demo on ideone.com


没有re.compile(只是为了理解):

def repl(match):
    return re.sub(r'Element.*?\b38\b', 'Element ABC', match.group(0))

print re.sub(r'BeginB[\s\S]+?EndB', repl, s)

这里的重要思想是re.sub的第二个参数可以是函数


不用功能就可以很好地做到这一点,但是您需要更新的regex模块,该模块支持\G\K

rx = re.compile(r'''
    (?:\G(?!\A)|BeginB)
    (?:(?!EndB)[\s\S])+?\K
    Element.+?\b38\b''', re.VERBOSE)

string = rx.sub('Element ABC', string)
print(string)

也请参阅另一个demo for this one on regex101.com