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

时间:2016-04-02 18:38:01

标签: regex

当所有组都可选时,我无法提取组。

上下文(如果您愿意,请跳至结束): 这是在将字符串与一堆正则表达式进行最佳匹配,并查看哪个表达式具有大多数组匹配的上下文中。

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

1: [A|B] [CD|DE|EF]-[1-1|1-2|2-2|2-3] [G|H]

但我希望用户输入错误,或者不包含空格或其他内容。

所以我可以针对字符串

测试它
A CD-1-1 G

并希望获得群组

  1. A
  2. CD
  3. 1-1
  4. 但也是,测试字符串

    DE-1-9 G
    

    我想得到

    1. DE
    2. G
    3. 所以这是我的正则表达式,以匹配以下可选组

      [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”字符(可能存在或不存在)。

      问题与我期望的组不匹配测试字符串

      A CD 1-9 G
      

      我希望小组

      1. A
      2. CD
      3. 但是我得到了

        1. A
        2. CD
        3. 为什么第三组之后不匹配?

3 个答案:

答案 0 :(得分:0)

Regex101在第2场比赛中抓住G。尝试添加g视频修饰符。

答案 1 :(得分:0)

我建议使用

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

请参阅regex demo

当然,重点是添加$锚点 - 字符串结束断言,使字符串匹配到最后。

接下来,当Paulo Almeida指出in the comment时,如果没有1-1,则必须有一些其他子模式匹配,例如1-9。由于CD / DE / EF可以是连字符或空格,因此我们要匹配除空格以外的0 +个字符或-[^ - ]匹配的字符。由于在1-1 / 1-2 / 2-2 / 2-3之后可以有空格,所以让我们匹配所有非空白字符。可以进行更多这样的调整,但这就是可以编写正则表达式的方法。

我还建议删除单个字符的替换并将它们转换为字符类。 (?: *)? = *

答案 2 :(得分:0)

这看起来有点像验证,几乎所有东西都是可选的 不过,你需要一些东西来帮助排队。

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

其次,数据部分之间的公共可选分隔符。这给了 它消耗的东西。可以使用空格和短划线[- ]

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

^(?=.)[- ]*([AB])?[- ]*(CD|DE|EF)?[- ]*(?:(1-[12]|2-[23])|\d-\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