正则表达式:匹配大集合中的确切数字

时间:2016-09-13 15:13:47

标签: regex

鉴于一个巨大的列表(超过一千个随机数字从00001到60031),匹配每个数字和只有那些数字的最佳方法是什么。

列表00001,00002,00003,00004,00006,00010,00016,00030,00039,00177,00187,00219,00239,00240,00241,00242,00245,00248,00250,00258,00260,....,20065,20069,20070,...,27005,27007,28006,29000,29400,30100,......

的示例

我知道我可以用超长的蛮力强迫它陈述,也许还有一些技巧,比如范围0000[1-6],但还有什么更聪明的东西吗?是的我知道我可以把它放在像python这样的脚本中,或者像数据库一样,并相应地匹配它但我必须在正则表达式中这样做,因为系统是以这种方式构建的。

到目前为止:(0000[1-46])|0001[06]|0003[09]|001[78]7|002[136]9|0024[0-58]|....

2 个答案:

答案 0 :(得分:1)

获取此应用http://www.regexformat.com,然后从工具菜单中运行
Strings to Regex - Ternary tree

将整个列表(数千)放入输入框,选择逗号作为分隔符
然后生成。

它将创建一个正则表达式,只需少于5步即可找到任何数字
在列表中非常快

Screenshot和示例字符串175,000 word Dictionary
这些数字不过是你要搜索的单词。

您提供的示例中的正则表达式:

(?<!\d)(?:00(?:0(?:0(?:1|2|3|4|6)|1(?:0|6)|3(?:0|9))|1(?:77|87)|2(?:19|39|4(?:0|1|2|5|8)|5(?:0|8)|60))|2(?:00(?:6(?:5|9)|70)|700(?:5|7)|8006|9(?:000|400))|30100)(?!\d)

扩展

 (?<! \d )
 (?:
      00
      (?:
           0
           (?:
                0
                (?: 1 | 2 | 3 | 4 | 6 )
             |  1
                (?: 0 | 6 )
             |  3
                (?: 0 | 9 )
           )
        |  1
           (?: 77 | 87 )
        |  2
           (?:
                19
             |  39
             |  4
                (?: 0 | 1 | 2 | 5 | 8 )
             |  5
                (?: 0 | 8 )
             |  60
           )
      )
   |  2
      (?:
           00
           (?:
                6
                (?: 5 | 9 )
             |  70
           )
        |  700
           (?: 5 | 7 )
        |  8006
        |  9
           (?: 000 | 400 )
      )
   |  30100
 )
 (?! \d )

编辑

添加Benchmark样本以测试效果。
显示使用带有/不带边界的正则表达式的结果:
请注意,几乎所有使用三元树生成的完整trie正则表达式 会有同样的替补,内容太多无关紧要。

Regex1:   (?<!\d)(?:00(?:0(?:0(?:1|2|3|4|6)|1(?:0|6)|3(?:0|9))|1(?:77|87)|2(?:19|39|4(?:0|1|2|5|8)|5(?:0|8)|60))|2(?:00(?:6(?:5|9)|70)|700(?:5|7)|8006|9(?:000|400))|30100)(?!\d)
Options:  < none >
Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   30
Elapsed Time:    1.75 s,   1747.23 ms,   1747235 µs


Regex2:   (?:00(?:0(?:0(?:1|2|3|4|6)|1(?:0|6)|3(?:0|9))|1(?:77|87)|2(?:19|39|4(?:0|1|2|5|8)|5(?:0|8)|60))|2(?:00(?:6(?:5|9)|70)|700(?:5|7)|8006|9(?:000|400))|30100)
Options:  < none >
Completed iterations:   50  /  50     ( x 1000 )
Matches found per iteration:   30
Elapsed Time:    1.13 s,   1129.65 ms,   1129650 µs


(50,000 iter) * (30 matches/iter) = 1,500,000 matches
-------------------------------------------------------------------------------------

Regex1 with boundary:  1,500,000 matches / 1.75 seconds  =   857,143 matches/second

Regex2 no boundary:    1,500,000 matches / 1.13 seconds  = 1,327,434 matches/second

答案 1 :(得分:0)

试试这个......

^(?:[0-5][0-9]{4}|600[0-2][0-9]|6003[01])(?<!00000)$

非捕获组中的第一个替代品通过匹配正好5个数字来捕获大多数数字,要求第一个数字为5或更小(请注意,这与00000匹配)。 接下来的两个交替使用60000-60031。 第二组是负面的后视,并且排除00000否则将匹配。

根据您使用的技术,负面外观可能不是一种选择。 PHP和python我相信支持它和Java肯定会... JavaScript我认为不是,但也许你可以通过二次检查检查一个值?