如何限制端口号验证1024到65535的正则表达式验证

时间:2014-08-22 15:13:50

标签: regex validation port

端口号应该只在1024到65535之间,不应该接受任何零值。 例如0000,不应该接受。我花了差不多一个小时。找到它所以发布答案。

3 个答案:

答案 0 :(得分:2)

^(102[4-9]|10[3-9]\d|1[1-9]\d{2}|[2-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$

以上代码允许您接受1024到65535之间的端口号,并且不接受任何0000。

答案 1 :(得分:2)

大多数情况下,分解又名分而治之) - 将复杂的问题分解为更小,更简单的问题 - 是一个很好的工具。所以,让我们把事情分解成简单的正则表达式。然后我们可以将它们组合成最终解决方案。我们可以首先注意到我们有一个4位数字范围(1024-9999)和5位数字范围(10000-65535)。

4位数字

在4位数字的范围内,范围的低端有一些我们需要处理的奇怪现象,但我们可以将其分解为简单的正则表达式:

1     0     2     [4-9] # matches 1024 - 1029
1     0     [3-9] [0-9] # matches 1030 - 1099
1     [1-9] [0-9] [0-9] # matches 1100 - 1999
[2-9] [0-9] [0-9] [0-9] # matches 2000 - 9999: the general case

5位数字

同样,5位数字的范围在范围的高端有一些奇怪的地方:

[1-5] [0-9] [0-9] [0-9] [0-9] # matches 10000 - 59999: the general case
6     [0-4] [0-9] [0-9] [0-9] # matches 60000 - 64999
6     5     [0-4] [0-9] [0-9] # matches 65000 - 65499
6     5     5     [0-2] [0-9] # matches 65500 - 65529
6     5     5     3     [0-5] # matches 65530 - 65535

这些都不是非常复杂。

正则表达式允许分组括号和交替(选择)与|。我们可以简单地组合上面的所有内容,在开始和结束处放下一些锚点并允许前导零并且你已经完成了:

^                              # anchor match at start-of-line, followed by
0*                             # zero or more leading zeros
  (102[4-9])                   #  1,024 -  1,029
| (10[3-9][0-9])               #  1,030 -  1,099
| (1[1-9][0-9][0-9])           #  1,100 -  1,999
| ([2-9][0-9][0-9][0-9])       #  2,000 -  9,999
| ([1-5][0-9][0-9][0-9][0-9])  # 10,000 - 59,999
| (6[0-4][0-9][0-9][0-9])      # 60,000 - 64,999
| (65[0-4][0-9][0-9])          # 65,000 - 65,499
| (655[0-2][0-9])              # 65,500 - 65,529
| (6553[0-5])                  # 65,530 - 65,535
$                              # anchor match at end-of-line

默认情况下,正则表达式引擎是贪婪的,并且根据*最左边最长的原则匹配:它将找到最长的匹配。如果有多个可能的最长匹配长度相等,则最左边的匹配是首选。

这个正则表达式不应该回溯,这意味着它不是最有效的形式。要消除回溯,您必须注意子表达式共享公共前缀,并且您需要将它们分解出来以使匹配具有预测性。但是,为了验证短文本字段,性能应该足够了。此外,我认为这可能更简单,更容易理解(对于下一个需要改变它的人。

如果你想学习如何优化正则表达式并从中获得最佳表现,你应该阅读Jeffrey Friedl的作品Mastering Regular Expressions

Mastering Regular Expressions cover

答案 2 :(得分:1)

您可以以优化的方式完成这项工作:

^(?:[2-5]\d{3,4}|1(?:[1-9]\d{2,3}|0(?:[3-9]\d{1,2}|[01]\d{2}|2(?:[4-9]\d?|[0-3]\d)))|6(?:[0-4]\d{2,3}|5(?:[0-4]\d{1,2}|5(?:[0-2]\d?|3[0-5]?|[4-9])|[6-9]\d)|[6-9]\d{2})|[7-9]\d{3})$

如何优化?

这个想法是通过首先放置最可能的替代方案来构建模式。 (例如,显然有更多以[2-5]开头的数字,而不是以1或6开头的数字)

第二个优化包括以正则表达式引擎永远不必返回的方式构建模式。 (换句话说,一旦正则表达式引擎开始在分支中找到匹配项,您确定它不需要在相同的交替中测试其他分支,因为它可以在当前分支中成功)

结果:您获得的图案时间稍长,但更快(但增益很轻)

缩进版

^
(?:
    [2-5]\d{3,4}              # 44000
  |
    1                         # 10976
    (?:
        [1-9]\d{2,3}               # 9900
      |
        0                          # 1076: 770, 200, 106:(66,40)
        (?: [3-9]\d{1,2} | [01]\d{2} | 2(?:[4-9]\d? | [0-3]\d) )
    )
  |
    6                         # 6536
    (?:
        [0-4]\d{2,3}                # 5500
      | 
        5                           # 636
        (?:
            [0-4]\d{1,2}                       # 550
          |
            5 (?: [0-2]\d? | 3[0-5]? | [4-9] ) # 46: 33, 7, 6
          |
            [6-9]\d                            # 40
        )
      |
        [6-9]\d{2}                  # 400
    )
  |
    [7-9]\d{3}                 # 3000
)$  # 64512 = 65535 - 1024 + 1