正则表达式匹配小变化的循环模式

2024-10-06 14:21:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图将重复模式与regex(在python3.9中)匹配,regex通常包含相同的数据,但有些区域的迭代次数不同(特别是以“CLD”和“REF”开头的行)

我试图从“LIN”匹配到从“HL”开始的行的末尾,这样我就可以在每次迭代之后进行进一步的匹配

这是我正在使用的数据的摘录

LIN**SI*ASN*BP*ITEM01*VP*1262702*CH*US
SN1**300*PC
PRF*5500015558****01
PID*F****DESCRIPTION01
REF*PK*000000051213
CLD*1*300*PLT71
REF*LS*0079393
HL*3*1*I
LIN**SI*ASN*BP*ITEM02*VP*1375541*CH*US
SN1**64*PC
PRF*5500014695****01
PID*F****DESCRIPTION02
REF*PK*000000051213
CLD*1*24*PLT71
REF*LS*0079393
CLD*1*40*PLT71
REF*LS*0079390
HL*4*1*I

到目前为止,我的正则表达式看起来是这样的(虽然离我想要达到的目标还有很长的距离)

LIN.*\nSN.*\nPRF.*\nPID.*\nREF.*\n

然而,由于“CLD”和“REF”行的数量不同,我在这一点上陷入了困境,因此它没有满足我的需要,我很确定这不是有效的正则表达式

LIN**SI*ASN*BP*CH11979*VP*1262702*CH*US
SN1**300*PC
PRF*5500015558****01
PID*F****SEAL INTEGRAL
REF*PK*000000051213

LIN**SI*ASN*BP*CH10439*VP*1375541*CH*US
SN1**64*PC
PRF*5500014695****01
PID*F****PUMP AS PRIMING
REF*PK*000000051213

我还尝试了下面的正则表达式(通过一些谷歌搜索),以避开各种各样的情况,而且效率更高,但它不起作用

LIN(.|\n)*HL.*

有人能帮我把这个整理一下吗


Tags: refchpidhlusbppcpk
2条回答

对于CLDREF的不同迭代,您可以使用交替|和量词+重复1次或多次,以匹配其中任何一行开始的行

^LIN.*\nSN.*\nPRF.*\nPID.*\n(?:(?:REF|CLD).*\n)+HL.*

解释

  • ^字符串的开头
  • LIN.*\nSN.*\nPRF.*\nPID.*\n匹配前4行
  • (?:(?:REF|CLD).*\n)+重复1+次,匹配REFCLD,行的其余部分和换行符
  • HL.*匹配HL和该行的其余部分

Regex demoPython demo

比如说

import re

s = ("LIN**SI*ASN*BP*ITEM01*VP*1262702*CH*US\n"
    "SN1**300*PC\n"
    "PRF*5500015558****01\n"
    "PID*F****DESCRIPTION01\n"
    "REF*PK*000000051213\n"
    "CLD*1*300*PLT71\n"
    "REF*LS*0079393\n"
    "HL*3*1*I\n"
    "LIN**SI*ASN*BP*ITEM02*VP*1375541*CH*US\n"
    "SN1**64*PC\n"
    "PRF*5500014695****01\n"
    "PID*F****DESCRIPTION02\n"
    "REF*PK*000000051213\n"
    "CLD*1*24*PLT71\n"
    "REF*LS*0079393\n"
    "CLD*1*40*PLT71\n"
    "REF*LS*0079390\n"
    "HL*4*1*I")
regex = r"^LIN.*\nSN.*\nPRF.*\nPID.*\n(?:(?:REF|CLD).*\n)+HL.*"
print(re.findall(regex, s, re.MULTILINE))

输出

[
'LIN**SI*ASN*BP*ITEM01*VP*1262702*CH*US\nSN1**300*PC\nPRF*5500015558****01\nPID*F****DESCRIPTION01\nREF*PK*000000051213\nCLD*1*300*PLT71\nREF*LS*0079393\nHL*3*1*I',
'LIN**SI*ASN*BP*ITEM02*VP*1375541*CH*US\nSN1**64*PC\nPRF*5500014695****01\nPID*F****DESCRIPTION02\nREF*PK*000000051213\nCLD*1*24*PLT71\nREF*LS*0079393\nCLD*1*40*PLT71\nREF*LS*0079390\nHL*4*1*I'
]

你可以用

(?m)^LIN[\w\W]*?\nHL.* # For any Python version
(?m)^LIN(?s:.*?)\nHL.* # For Python 3.6+

regex demo

详细信息

  • (?m)-一个内联的re.M修饰符标志,用于使^匹配任何行的起始位置
  • ^-行的开始
  • LIN-LIN字符串
  • [\w\W]*?/(?s:.*?)-任何零个或多个字符,尽可能少
  • \n-换行符
  • HL-HL
  • .*-行的其余部分

Python demo

import re
text = "LIN**SI*ASN*BP*ITEM01*VP*1262702*CH*US\nSN1**300*PC\nPRF*5500015558****01\nPID*F****DESCRIPTION01\nREF*PK*000000051213\nCLD*1*300*PLT71\nREF*LS*0079393\nHL*3*1*I\nLIN**SI*ASN*BP*ITEM02*VP*1375541*CH*US\nSN1**64*PC\nPRF*5500014695****01\nPID*F****DESCRIPTION02\nREF*PK*000000051213\nCLD*1*24*PLT71\nREF*LS*0079393\nCLD*1*40*PLT71\nREF*LS*0079390\nHL*4*1*I"
print(re.findall(r'(?m)^LIN(?s:.*?)\nHL.*', text))

输出:

[
 
 'LIN**SI*ASN*BP*ITEM01*VP*1262702*CH*US\nSN1**300*PC\nPRF*5500015558****01\nPID*F****DESCRIPTION01\nREF*PK*000000051213\nCLD*1*300*PLT71\nREF*LS*0079393\nHL*3*1*I', 
 'LIN**SI*ASN*BP*ITEM02*VP*1375541*CH*US\nSN1**64*PC\nPRF*5500014695****01\nPID*F****DESCRIPTION02\nREF*PK*000000051213\nCLD*1*24*PLT71\nREF*LS*0079393\nCLD*1*40*PLT71\nREF*LS*0079390\nHL*4*1*I'
]

相关问题 更多 >