在一个字符串中(实际上更大):
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
块中。该怎么做?
答案 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
没有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)