You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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)

运行这个代码后,会准确输出13,也就是你要的目标结果。

改进方案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)

为什么你的原方案会出错?

  1. 原正则\n?\d.*?xxx 10:在re.DOTALL模式下,.*?会匹配任意字符(包括换行),它会从第一个数字开始,一直匹配到最近的xxx 10,但不会考虑中间是否跨过了其他作业的编号,所以会把多个作业的内容连在一起匹配。
  2. 你尝试的负前瞻(?!(?:\n?xxx \d{2}\n)*):这个断言的逻辑不对——它是在检查「后面没有若干个xxx \d{2}行」,但我们需要的是「在匹配到xxx 10之前,不会遇到新的作业编号」,方向和目标都偏离了,所以无法生效。

内容的提问来源于stack exchange,提问作者Frederic Faure

火山引擎 最新活动