Regex 正则表达式匹配和所有可选组

Regex 正则表达式匹配和所有可选组,regex,Regex,我在提取组时遇到问题,因为所有组都可能是可选的 上下文(如果愿意,请跳到结尾): 这是在一个字符串与一组正则表达式最佳匹配的上下文中,并查看哪个表达式具有最多的组匹配 例如,我可能有一个潜在的格式 1: [A|B] [CD|DE|EF]-[1-1|1-2|2-2|2-3] [G|H] 但我希望用户输入错误,或者不包含空格或其他内容 所以我可以用字符串来测试它 A CD-1-1 G 并且想要得到团体 A 光盘 1-1 G 而且,对于测试字符串 DE-1-9 G A CD 1-9 G 我想

我在提取组时遇到问题,因为所有组都可能是可选的


上下文(如果愿意,请跳到结尾): 这是在一个字符串与一组正则表达式最佳匹配的上下文中,并查看哪个表达式具有最多的组匹配

例如,我可能有一个潜在的格式

1: [A|B] [CD|DE|EF]-[1-1|1-2|2-2|2-3] [G|H]
但我希望用户输入错误,或者不包含空格或其他内容

所以我可以用字符串来测试它

A CD-1-1 G
并且想要得到团体

  • A
  • 光盘
  • 1-1
  • G
  • 而且,对于测试字符串

    DE-1-9 G
    
    A CD 1-9 G
    
    我想买一个

  • G

  • 这是我的正则表达式,用于匹配以下可选组

    [A|B] [CD|DE|EF]-[1-1|1-2|2-2|2-3] [G|H]
    
    正则表达式:

    (A|B)?(?: *)?(CD|DE|EF)?(?:-|(?: ))?((?:1-(?:1|2))|(?:2-(?:2|3)))?(?: *)?(G|H)?
    
    分解我认为应该如何工作

    • (A | B)—匹配“A”或“B”字符(可能存在也可能不存在)
    • (?:*)?-匹配一些空格字符(也可能不存在),但不需要组
    • (CD|DE|EF)?-匹配“CD”、“DE”或“EF”(可能存在也可能不存在)
    • (?:-|(?:)?-匹配“-”或某些空格(可能有也可能没有)
    • ((?:1-(?:1 | 2))|(?:2-(?:2 | 3)))-匹配[1-[1 | 2]]或[2-[2 | 3]](可能正确,也可能不正确/完全正确)
    • (?:*)?-匹配一些空格字符(也可能不存在),但不需要组
    • (G | H)—匹配“G”或“H”字符(可能存在也可能不存在)
    与测试字符串不匹配的问题

    DE-1-9 G
    
    A CD 1-9 G
    
    我期待着团体

  • A
  • 光盘
  • G
  • 但我明白了

  • A
  • 光盘

  • 为什么在第三组之后不匹配?

    Regex101捕捉匹配2中的
    G
    。尝试添加
    g
    lobal修饰符。

    我建议使用

    ^([AB]?) *(?:(CD|DE|EF)?|[^- ]*)[- ]?(?:(1-[12]|2-[23])?|\S*) *([GH]?)$
    

    当然,主要的一点是添加
    $
    锚定-字符串结束断言,使字符串匹配到其结束

    接下来,正如所指出的,如果没有
    1-1
    ,则必须有其他子模式来匹配,例如
    1-9
    。由于
    CD
    /
    DE
    /
    EF
    之后可以是连字符或空格,因此让我们将空格或
    -
    以外的0+字符与
    [^-]
    匹配。由于
    1-1
    /
    1-2
    /
    2-2
    /
    2-3
    后面可能有空格,所以让我们匹配所有非空白字符。可以有更多这样的调整,但这就是工作正则表达式的编写方式


    我还建议去掉单个字符的交替,并将它们转换为字符类<代码>(?:*)?=
    *

    这看起来有点像验证,几乎所有内容都是可选的。
    不过,你还是需要一些东西来帮助你把事情安排好

    首先,锚定
    ^$
    。需要此或其他一些伪锚(文本)
    给它一个开始和结束,以集中搜索

    第二,数据部分之间的公共可选分隔符。这就产生了
    它是一种消费品。可以使用空格和破折号
    [-]

    这将从左到右排列零件。它们都是可选的

    ^(?=)[-]*([AB])?[-]*(CD | DE | EF)?[-]*(?:(1-[12]| 2-[23])\d-[-]*([GH])?[-]*$

    下面是一些解释:

     ^                             # Beginning of string
     (?= . )                       # Only used to insure not a blank line
     [- ]*                         # Optional specific delimiters
     ( [AB] )?                     # (1), Optional A or B
     [- ]*                         # Optional specific delimiters
     ( CD | DE | EF )?             # (2), Optional CD or DE or EF
     [- ]*                         # Optional specific delimiters
     (?:                           # Optional numb-numb
          ( 1- [12] | 2- [23] )         # (3), Only ones we care about
       |                              # or,
          \d - \d                       # Any numb-numb
     )?
     [- ]*                         # Optional specific delimiters
     ( [GH] )?                     # (4), Optional G or H
     [- ]*                         # Optional specific delimiters
     $                             # End of string
    
    所有捕获组都设置为可选(而不是其内容),因此这会使
    很容易测试它们是否有数据(NULL或长度>0,取决于引擎)

    测试:

    为了进行测试,我使用了多行模式,并将所有条目作为一个单独的条目包含进来
    字符串(如果一次只检查一个输入,请不要使用此模式)

    输入:

    A CD 1-9 G
    DE-1-9 G
    A CD-1-1 G
    AG
    4-8
    
    输出:

     **  Grp 0 -  ( pos 0 , len 10 ) 
    A CD 1-9 G  
     **  Grp 1 -  ( pos 0 , len 1 ) 
    A  
     **  Grp 2 -  ( pos 2 , len 2 ) 
    CD  
     **  Grp 3 -  NULL 
     **  Grp 4 -  ( pos 9 , len 1 ) 
    G  
    -----------
     **  Grp 0 -  ( pos 12 , len 8 ) 
    DE-1-9 G  
     **  Grp 1 -  NULL 
     **  Grp 2 -  ( pos 12 , len 2 ) 
    DE  
     **  Grp 3 -  NULL 
     **  Grp 4 -  ( pos 19 , len 1 ) 
    G  
    -----------
     **  Grp 0 -  ( pos 22 , len 10 ) 
    A CD-1-1 G  
     **  Grp 1 -  ( pos 22 , len 1 ) 
    A  
     **  Grp 2 -  ( pos 24 , len 2 ) 
    CD  
     **  Grp 3 -  ( pos 27 , len 3 ) 
    1-1  
     **  Grp 4 -  ( pos 31 , len 1 ) 
    G  
    -----------
     **  Grp 0 -  ( pos 34 , len 2 ) 
    AG  
     **  Grp 1 -  ( pos 34 , len 1 ) 
    A  
     **  Grp 2 -  NULL 
     **  Grp 3 -  NULL 
     **  Grp 4 -  ( pos 35 , len 1 ) 
    G  
    -----------
     **  Grp 0 -  ( pos 38 , len 3 ) 
    4-8  
     **  Grp 1 -  NULL 
     **  Grp 2 -  NULL 
     **  Grp 3 -  NULL 
     **  Grp 4 -  NULL 
    

    我认为Wiktor的模式是可行的,为了回答你的问题,可以选择使用
    [1-1 | 1-2 | 2-2 | 2-3]
    ,但是只有在没有任何东西的情况下,'G'才会匹配。
    1-9
    会破坏模式。Wiktor通过在每个中心模式中允许一个空的替代方案来解决这个问题。这是另一个很好的答案。谢谢你看了。@THRND-没问题。这是一个20美元的答案,因为它提供了一种可以垂直应用的技术。快速的$2答案就像,一次性的,使用一次就不能再使用。。