Python多行正则表达式匹配问题:提取关联指定IPref的作业编号
解决IPref关联作业编号提取的正则问题
看起来你遇到的核心问题是当前正则会跨作业块匹配,导致提取了错误的内容。我们可以通过调整正则逻辑,精准锁定单个作业块来解决这个问题,下面是具体方案:
核心思路
每个作业块的结构是「行首数字(作业编号) + 多行内容 + xxx [IPref]」,我们需要确保正则只在单个作业块内匹配,不会跨过下一个作业的编号行。
改进方案1:精准正则匹配
使用带有负前瞻的正则,确保在匹配到xxx 10之前,不会遇到新的作业编号(行首的数字):
#!/usr/bin/python import re import sys with open('test2.xml','r') as fic: texte = fic.read() # 正则说明: # (?m):开启多行模式,让^匹配行首 # ^(\d+):捕获行首的作业编号 # (?:(?!^\d+)[\s\S])*?:非捕获组,匹配任意字符(包括换行),直到遇到下一个作业编号行首就停止 # xxx 10:匹配目标IPref行 pattern = r'(?m)^(\d+)(?:(?!^\d+)[\s\S])*?xxx 10' job_numbers = re.findall(pattern, texte) print("IPref=10对应的作业编号:") for num in job_numbers: print(num)
运行这个代码后,会准确输出1和3,也就是你要的目标结果。
改进方案2:分割作业块后检查(更直观)
如果觉得正则逻辑太绕,也可以先把文本分割成单个作业块,再逐个检查是否包含xxx 10:
#!/usr/bin/python import re import sys with open('test2.xml','r') as fic: texte = fic.read() # 按行首的数字分割作业块 job_blocks = re.split(r'^(?=\d+)', texte, flags=re.MULTILINE) # 过滤掉空的块 job_blocks = [block.strip() for block in job_blocks if block.strip()] result = [] for block in job_blocks: # 提取当前作业的编号 num_match = re.match(r'^(\d+)', block) # 检查当前块是否包含目标IPref if num_match and 'xxx 10' in block: result.append(num_match.group(1)) print("IPref=10对应的作业编号:") for num in result: print(num)
为什么你的原方案会出错?
- 原正则
\n?\d.*?xxx 10:在re.DOTALL模式下,.*?会匹配任意字符(包括换行),它会从第一个数字开始,一直匹配到最近的xxx 10,但不会考虑中间是否跨过了其他作业的编号,所以会把多个作业的内容连在一起匹配。 - 你尝试的负前瞻
(?!(?:\n?xxx \d{2}\n)*):这个断言的逻辑不对——它是在检查「后面没有若干个xxx \d{2}行」,但我们需要的是「在匹配到xxx 10之前,不会遇到新的作业编号」,方向和目标都偏离了,所以无法生效。
内容的提问来源于stack exchange,提问作者Frederic Faure




