正则表达式使用 Notepad++ 在第一个字符串和另一个字符串的第一个实例之间查找字符串

Regex find string between first string and the first instance of another string using Notepad++

抱歉 - 为了清楚起见,我已经对其进行了编辑(并且我稍后尝试删除 post 中的粗体,但它并没有消失......源文件中的星号正在抛出它关):

我正在解析医疗索赔文件,需要找到一个字符串与另一个字符串之间匹配的任何实例,但前提是该匹配出现在满足另一个字符串之前。

我要搜索的特定字符串是 DTP*431 和 REF*6R(我将 DTP*431 作为其中的一部分,因为它在某些情况下会被删除)。

如果紧跟在 DTP*431*D8* 之后的 8 位数字与文件中紧跟在下一个 DTP*472*RD8* 之后的 8 位数字完全匹配,我需要正则表达式 return 匹配,并且在 DTP*472*RD8*

的下一个实例之后的 8 位数字之后不继续搜索

此示例不应 return 匹配,因为紧跟在 DTP*431*D8* (20150101) 之后的 8 位数字与紧跟在下一个 DTP*472*RD8* 实例之后的 8 位数字不匹配(20150102):

DTP*431*D8*20150101~
[中间可变文本]
LX*1~
DTP*472*RD8*20150102-20150102~
REF*6R*[更多信息]~
[中间可变文本]
DTP*431*D8*20141231~
[中间可变文本]
LX*1~
DTP*472*RD8*20150103-20150103~
REF*6R*[更多信息]~

此示例应该 return 匹配,但应该只反映匹配,因为紧跟在 DTP*431*D8* (20150101) 之后的 8 位数字与紧跟在第一个实例 DTP*472*RD8* 之后的 8 位数字完全匹配出现在文件 (20150101) 中:


DTP*431*D8*20150101~
[中间可变文本]
LX*1~
DTP*472*RD8*20150101-20150101~
REF*6R*[更多信息]~
[中间可变文本]
DTP*431*D8*20141231~
[中间可变文本]
LX*1~
DTP*472*RD8*20150102-20150102~
REF*6R*[更多信息]~

此示例不应 return 匹配,因为即使在 DTP*431*D8* 实例和 DTP*472*RD8* (20150101) 实例之后的前 8 位数字之间存在匹配,它也是不是提供该匹配的 DTP*472*RD8* 的下一个实例:

DTP*431*D8*20150101~
[中间可变文本]
LX*1~
DTP*472*RD8*20150103-20150103~
REF*6R*[更多信息]~
[中间可变文本]
DTP*431*D8*20141231~
[中间可变文本]
LX*1~
DTP*472*RD8*20150101-20150101~
REF*6R*[更多信息]~

这是我目前所拥有的:

(DTP*431*D8*)(?<=\DTP*431*D8*)([0-9]{8})(.*?)(?=\DTP*472)(DTP*472*RD8* )(\2)

...但是如果 DTP*472 的第一个实例中的日期不匹配,它将继续经过第一个 DTP*472 并查找直到找到日期与 \1 元素匹配的任何 DTP*472。

因此,如果我搜索以下文本,它会(不希望地)匹配粗体部分:

DTP*431*D8*20150101~
[中间可变文字]
LX*1~
DTP*472*RD8*20150102-20150102~
REF*6R*[更多信息]~
[中间可变文字]
DTP*431*D8*20141231~
[中间可变文字]
LX*1~
DTP*472*RD8*20150101-20150101~
REF*6R*[更多信息]~


我想要做的是删除整行 DTP*431*D8* 如果紧跟在 DTP*431*D8* 之后的 8 位数字与紧跟在下一个 DTP*472*RD8* 实例之后的 8 位数字完全匹配

这是我从网上获取并修改的示例(我不能使用实际数据)。此项应产生匹配项:

ISA*00* *01*SECRET ZZSUBMITTERS.ID ZZRECEIVERS.ID *150101*0001*^*00501*00000001 *1*T*:~
GSHC发件人代码*收件人代码*0*0001*1*X*005010X222~
ST*837*0021*005010X222~
BHT*0019*00*244579*20150101*1023*CH~
NM1*41*2*计费服务*****46*9999999~
PERICDOE*JOHN*3055552222*EX*111~
NM1*40*2*ABC保险公司*****46*1111111~
HL*1* * 20*1~
PRVBIPXC*1234597890~
NM1*85*2*医生办公室*****XX*9876543210~
N3*1234 主站~
N4*洛杉矶*CA*11111~
REF*EI*222222222~
NM1*87*2~
N3*2345 主街~
N4*洛杉矶*CA*11111~
HL*2*1*22*1~
SBR*P********CI~
NM1*IL*1*DOE*JANE****MI*11332255~
伤害*D8*10000101*O~
NM1*PR*2*DEF 保险公司*****PI*999996666~
HL*3*2*23*0~
帕特*19~
NM1*QC*1*JONES*JOHN~
N3*111 N 主站~
N4*洛杉矶*CA*22222~
伤害*D8*10000202*O~
CLM*888888*1***11:B:1*YAY*I~
DTP*431*D8*20150201~
REF*D9*1~
HI*BK:9999*BF:V999~
LX*1~
SV1*HC:99999*1*UN*1***1~
DTP*472*RD8*20150101-20150201~
REF*6R*000001~
SE*33*0021~
GE*1*1~
国际能源署*1*000000001~

使用这个,如果找到我的匹配项,我将完全删除 DTP*431*D8 行,然后文件将显示如下:

ISA*00* *01*SECRET ZZSUBMITTERS.ID ZZRECEIVERS.ID *150101*0001*^*00501*00000001 *1*T*:~
GSHC发件人代码*收件人代码*0*0001*1*X*005010X222~
ST*837*0021*005010X222~
BHT*0019*00*244579*20150101*1023*CH~
NM1*41*2*计费服务*****46*9999999~
PERICDOE*JOHN*3055552222*EX*111~
NM1*40*2*ABC保险公司*****46*1111111~
HL*120*1~
PRVBIPXC*1234597890~
NM1*85*2*医生办公室*****XX*9876543210~
N3*1234 主站~
N4*洛杉矶*CA*11111~
REF*EI*222222222~
NM1*87*2~
N3*2345 主街~
N4*洛杉矶*CA*11111~
HL*2*1*22*1~
SBR*P********CI~
NM1*IL*1*DOE*JANE****MI*11332255~
伤害*D8*10000101*O~
NM1*PR*2*DEF 保险公司*****PI*999996666~
HL*3*2*23*0~
帕特*19~
NM1*QC*1*JONES*JOHN~
N3*111 N 主站~
N4*洛杉矶*CA*22222~
伤害*D8*10000202*O~
CLM*888888*1***11:B:1*YAYI~
REF
D9*1~
HI*BK:9999*BF:V999~
LX*1~
SV1*HC:99999*1*UN*1***1~
DTP*472*RD8*20150101-20150201~
REF*6R*000001~
SE*33*0021~
GE*1*1~
国际能源署*1*000000001~


相反,此项不会匹配,文件将保持原样:

ISA*00* *01*SECRET ZZSUBMITTERS.ID ZZRECEIVERS.ID *150101*0001*^*00501*00000001 *1*T*:~
GSHC发件人代码*收件人代码*0*0001*1*X*005010X222~
ST*837*0021*005010X222~
BHT*0019*00*244579*20150101*1023*CH~
NM1*41*2*计费服务*****46*9999999~
PERICDOE*JOHN*3055552222*EX*111~
NM1*40*2*ABC保险公司*****46*1111111~
HL*1
20*1~
PRVBIPXC*1234597890~
NM1*85*2*医生办公室*****XX*9876543210~
N3*1234 主站~
N4*洛杉矶*CA*11111~
REF*EI*222222222~
NM1*87*2~
N3*2345 主街~
N4*洛杉矶*CA*11111~
HL*2*1*22*1~
SBR*P********CI~
NM1*IL*1*DOE*JANE****MI*11332255~
伤害*D8*10000101*O~
NM1*PR*2*DEF 保险公司*****PI*999996666~
HL*3*2*23*0~
帕特*19~
NM1*QC*1*JONES*JOHN~
N3*111 N 主站~
N4*洛杉矶*CA*22222~
伤害*D8*10000202*O~
CLM*888888*1***11:B:1*YAY*I~
DTP*431*D8*20150201~
REF*D9*1~
HI*BK:9999*BF:V999~
LX*1~
SV1*HC:99999*1*UN*1***1~
DTP*472*RD8*20150102-20150202~
REF*6R*000001~
SE*33*0021~
GE*1*1~
国际能源署*1*000000001~

我不太确定我是否理解你的问题,但假设你想捕获 DTP*431REF*6R 之间的内容,包括 DTP*431,那么你可以使用这个正则表达式:

(DTP\*431.*?)REF\*6R

Working demo

您将内容保存到丢弃 REF*6R 的捕获组中。您可以看到蓝色的匹配项和绿色的捕获组内容。

好的,重做。现在查看您的样品。
它变得非常复杂。有很多事情正在发生。

试图解释它会很乏味。所以,我把所有的解释都放在
正则表达式注释。

只需将匹配项替换为“”即可。

格式化、调试、测试和分析 RegexFormat 5

 # (?sm)(?:^[ \t]*DTP\*\d{3}\*R?D\d\*(\d{8})[^\r\n]*\r?\n(?=(?:(?!^[ \t]*DTP\*\d{3}\*R?D\d\*).)*^[ \t]*DTP\*\d{3}\*R?D\d\*(?:|\d{8}-).*?^[ \t]*REF\*6R)|^[ \t]*DTP\*\d{3}\*R?D\d\*\d{8}-(\d{8})[^\r\n]*\r?\n(?=(?:(?!^[ \t]*DTP\*\d{3}\*R?D\d\*).)*^[ \t]*DTP\*\d{3}\*R?D\d\*(?:|\d{8}-).*?^[ \t]*REF\*6R))

 (?sm)
 (?:
      ^ [ \t]* DTP\* \d{3} \*R?D \d \*
      ( \d{8} )                           # (1), Checking "first" NUMBER spot
      [^\r\n]* \r? \n                     # Grab the rest of this line

      (?=                                 # Lookahead 
           (?:                                 # Not a DTP line
                (?! ^ [ \t]* DTP\* \d{3} \*R?D \d \* )
                . 
           )*
           ^ [ \t]* DTP\* \d{3} \*R?D \d \*    # The very next 'DTP' line
           (?:  | \d{8} -  )               # Number must be in one of these spots
           .*? ^ [ \t]* REF\*6R                # The ending
      )

   |                                    ## Or, 

      ^ [ \t]* DTP\* \d{3} \*R?D \d \*
      \d{8} - 
      ( \d{8} )                           # (2), Checking "second" NUMBER spot
      [^\r\n]* \r? \n                     # Grab the rest of this line

      (?=                                 # Lookahead
           (?:                                 # Not a DTP line
                (?! ^ [ \t]* DTP\* \d{3} \*R?D \d \* )
                . 
           )*
           ^ [ \t]* DTP\* \d{3} \*R?D \d \*    # The very next 'DTP' line
           (?:  | \d{8} -  )               # Number must be in one of these spots
           .*? ^ [ \t]* REF\*6R                # The ending
      )
 )

您可能希望将 Lookaheads 变成捕获组((?=..)(..) 然后调整反向引用以指向 </code>和 <code>.
此时替换只是 </code> 或 <code>.
这样做是将搜索位置移到结尾处,避免可能的重叠。

 # (?sm)(?:^[ \t]*DTP\*\d{3}\*R?D\d\*(\d{8})[^\r\n]*\r?\n((?:(?!^[ \t]*DTP\*\d{3}\*R?D\d\*).)*^[ \t]*DTP\*\d{3}\*R?D\d\*(?:|\d{8}-).*?^[ \t]*REF\*6R)|^[ \t]*DTP\*\d{3}\*R?D\d\*\d{8}-(\d{8})[^\r\n]*\r?\n((?:(?!^[ \t]*DTP\*\d{3}\*R?D\d\*).)*^[ \t]*DTP\*\d{3}\*R?D\d\*(?:|\d{8}-).*?^[ \t]*REF\*6R))

 (?sm)
 (?:
      ^ [ \t]* DTP\* \d{3} \*R?D \d \*
      ( \d{8} )                           # (1), Checking "first" NUMBER spot
      [^\r\n]* \r? \n                     # Grab the rest of this line

      (                                   # (2 start), Part to be written back 
           (?:                                 # Not a DTP line
                (?! ^ [ \t]* DTP\* \d{3} \*R?D \d \* )
                . 
           )*
           ^ [ \t]* DTP\* \d{3} \*R?D \d \*    # The very next 'DTP' line
           (?:  | \d{8} -  )               # Number must be in one of these spots
           .*? ^ [ \t]* REF\*6R                # The ending
      )                                   # (2 end)

   |                                    ## Or, 

      ^ [ \t]* DTP\* \d{3} \*R?D \d \*
      \d{8} - 
      ( \d{8} )                           # (3), Checking "second" NUMBER spot
      [^\r\n]* \r? \n                     # Grab the rest of this line

      (                                   # (4 start), Part to be written back
           (?:                                 # Not a DTP line
                (?! ^ [ \t]* DTP\* \d{3} \*R?D \d \* )
                . 
           )*
           ^ [ \t]* DTP\* \d{3} \*R?D \d \*    # The very next 'DTP' line
           (?:  | \d{8} -  )               # Number must be in one of these spots
           .*? ^ [ \t]* REF\*6R                # The ending
      )                                   # (4 end)
 )