【问题标题】:Regex find string between first string and the first instance of another string using Notepad++正则表达式使用 Notepad++ 在第一个字符串和另一个字符串的第一个实例之间查找字符串
【发布时间】:2015-03-11 16:37:11
【问题描述】:

抱歉 - 为了清楚起见,我已对此进行了编辑(我已尝试在帖子后面删除粗体,但它并没有消失......源文件中的星号将其丢弃):

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

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

如果紧跟在 DTP*431*D8* 之后的 8 位数字与文件中紧跟在 DTP*472*RD8* 下一个实例之后的 8 位数字完全匹配,我需要正则表达式返回匹配项,并且不继续搜索紧接在下一个 DTP*472*RD8* 实例之后的 8 位数字之后

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

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

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


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

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

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

到目前为止,这是我所拥有的:

(DTP*431*D8*)(?
...但如果 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*医生办公室*****XXX*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~
DMG*D8*10000101*O~
NM1*PR*2*DEF 保险公司*****PI*999996666~
HL*3*2*23*0~
拍*19~
NM1*QC*1*JONES*JOHN~
N3*111 N MAIN ST~
N4*洛杉矶*CA*22222~
DMG*D8*10000202*O~
CLM*888888*1***11:B:1*YAY*I~
排版*431*D8*20150201~
参考*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~
通用电气*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*医生办公室*****XXX*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~
DMG*D8*10000101*O~
NM1*PR*2*DEF 保险公司*****PI*999996666~
HL*3*2*23*0~
拍*19~
NM1*QC*1*JONES*JOHN~
N3*111 N MAIN ST~
N4*洛杉矶*CA*22222~
DMG*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~
通用电气*1*1~
IEA*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*医生办公室*****XXX*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~
DMG*D8*10000101*O~
NM1*PR*2*DEF 保险公司*****PI*999996666~
HL*3*2*23*0~
拍*19~
NM1*QC*1*JONES*JOHN~
N3*111 N MAIN ST~
N4*洛杉矶*CA*22222~
DMG*D8*10000202*O~
CLM*888888*1***11:B:1*YAY*I~
排版*431*D8*20150201~
参考*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~
通用电气*1*1~
国际能源署*1*000000001~

【问题讨论】:

  • 问题不是开始,而是结束。在您的第一个示例中,是什么让它超越了 REF*6R*[ ?您在寻找平衡的开始/结束吗?
  • 我不确定什么是平衡的开始/结束。我希望我在这方面做得更好,但我学到的大部分东西都来自于没有正式指导的网站。我现在正在阅读平衡的开始和结束,并且可能很快就会有答案。 :)
  • 完全不清楚。请编辑您的问题,添加 1)您想要重现的确切规则,2)几个示例,清楚地解释为什么它们应该失败或成功
  • 我认为您为我指明了正确的方向。问题是我不知道我不知道什么。那我会这样做吗? (?'open'(DTP*431*D8*)([0-9]{8}))+(?'-open'DTP*472*\2)+
  • @BartlebytheScrivener 您的问题不够清楚,您可以发布示例数据和预期输出吗?

标签: regex string search notepad++


【解决方案1】:

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

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

只需将匹配替换为“”,就可以了。

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\*(?:\1|\d{8}-\1).*?^[ \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\*(?:\2|\d{8}-\2).*?^[ \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
           (?: \1 | \d{8} - \1 )               # 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
           (?: \2 | \d{8} - \2 )               # Number must be in one of these spots
           .*? ^ [ \t]* REF\*6R                # The ending
      )
 )

您可能希望将 Lookaheads 转换为捕获组((?=..)(..),然后调整后向引用以指向 \1\3
此时替换只是\2\4$2$4
这样做是将搜索位置移动到结尾,避免可能的重叠。

 # (?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\*(?:\1|\d{8}-\1).*?^[ \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\*(?:\3|\d{8}-\3).*?^[ \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
           (?: \1 | \d{8} - \1 )               # 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
           (?: \3 | \d{8} - \3 )               # Number must be in one of these spots
           .*? ^ [ \t]* REF\*6R                # The ending
      )                                   # (4 end)
 )

【讨论】:

  • 我希望我编辑的条目能够清晰,但这与我的第一个示例有相同的问题。如果 DTP*472*RD8* 的第一个实例不匹配,它将继续搜索,直到找到匹配的实例。
  • @BartlebytheScrivener - 幸运的是,这正是这个正则表达式所做的。你检查了 Output 吗?
  • 编辑:我想我错过了一些东西。它实际上是从我的生产文件中的一个不同的 DTP 段开始的,这让我大吃一惊。我现在正在重新测试。
  • 我已经尝试将其编辑为仅使用 431 开始和 472 结束,并且它会超过第一个 472 以查找 472 的下一个实例,其日期与第一个匹配.我也尝试过将 472 保留为 \d{3} 无济于事。
  • @BartlebytheScrivener - 看看修改后的。
【解决方案2】:

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

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

Working demo

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

【讨论】:

    猜你喜欢
    • 2014-07-17
    • 1970-01-01
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    相关资源
    最近更新 更多