使用正则表达式匹配其中包含连续5个递增数字的数字

时间:2019-01-26 20:09:58

标签: regex

首先,有人问before。但是,我无法对其进行修改以满足我的要求。

简而言之:我希望有一个正则表达式与表达式匹配,当且仅当它仅包含数字,并且表达式中某处有5个(或更多)递增连续数字时。

我了解……的逻辑

^(?=\d{5}$)1*2*3*4*5*6*7*8*9*0*$

但是,这会将表达式限制为5位数字。我希望表达式前后都可以有数字。因此1111345671111应该匹配,而11111不应该匹配。

我认为这可能有效:

^[0-9]*(?=\d{5}0*1*2*3*4*5*6*7*8*9*)[0-9]*$

我解释为:

  • ^$:整个表达式只能包含这两个符号之间的内容

  • [0-9]*0-9之间的任何数字,0或更多次,后跟:

  • (?=\d{5}0*1*2*3*4*5*6*7*8*9*):找到至少5个递增数字的部分,后跟:

  • [0-9]*0-9之间的任何数字,0次或多次。

但是此正则表达式不正确,例如11111匹配。如何使用正则表达式解决此问题?因此要匹配的表达式示例:

  • 00001459000
  • 12345

这不应该匹配:

  • abc12345
  • 9871234444

2 个答案:

答案 0 :(得分:23)

尽管可以使用纯正则表达式解决此问题(严格递增的五位数字字符串是有限的,所以您可以枚举所有字符串),但它不适用于正则表达式。

也就是说,如果必须的话,这就是我要做的事情:

^\d*(?=\d{5}(\d*)$)0?1?2?3?4?5?6?7?8?9?\1$

核心思想:0?1?2?3?4?5?6?7?8?9?匹配一个递增的数字子字符串,但不限制其长度。每个部分都是可选的,因此它可以匹配从""(空字符串)到完整的"0123456789"的所有内容。

我们可以通过将五位数字的预读与任意后缀(我们捕获到的)和后向引用\1(必须与前瞻匹配的后缀精确组合)相结合来强制它精确匹配5个字符,确保我们现在已经向前移动了字符串中的5个字符)。

实时演示:https://regex101.com/r/03rJET/3

(顺便说一句,您对(?=\d{5}0*1*2*3*4*5*6*7*8*9*)的解释是不正确的:它期待完全匹配5个数字,后跟0个或多个出现的0,然后是0个或多个出现的{{ 1}}等)

答案 1 :(得分:3)

因为预先不知道递增数字的开始位置,并且连续的递增数字不会在字符串的结尾处结束,所以链接的答案的简洁模式在这里不起作用。我认为没有重复就不可能做到这一点。在所有增加数字的可能性之间交替。 0之后必须是[1-9]。 (0(?=[1-9])1之后必须是[2-9]2之后必须是[3-9],依此类推。在一组中的这些可能性之间交替,并重复该组四次,然后匹配任意一位数字(前一组中最后一位重复数字的前瞻将确保这第5位数字也是按顺序排列的。

首先 lookahead 表示数字,然后是字符串的结尾,然后匹配上述替代项,然后匹配一个或多个数字:

^(?=\d+$)\d*?(?:0(?=[1-9])|1(?=[2-9])|2(?=[3-9])|3(?=[4-9])|4(?=[5-9])|5(?=[6-9])|6(?=[7-9])|7(?=[89])|8(?=9)){4}\d+

分开以提高可读性:

^(?=\d+$)\d*?
  (?:
    0(?=[1-9])|
    1(?=[2-9])|
    2(?=[3-9])|
    3(?=[4-9])|
    4(?=[5-9])|
    5(?=[6-9])|
    6(?=[7-9])|
    7(?=[89])|
    8(?=9)
  ){4}
\d+

\d*?的第一行中的惰性量词不是不必要的,但是它使模式更有效(否则,它最初会贪婪地匹配整个字符串,因此需要大量失败的替换和回溯,直到字符串末尾至少5个字符为止)

https://regex101.com/r/03rJET/2

这很丑,但是行得通。