正则表达式匹配不同长度的多个范围

时间:2014-01-22 13:49:35

标签: regex range

我需要验证用户输入的值是否为以下之一:

  • 7位数字,范围从7000000 - 7999999
  • 一个9位数字,范围从777000000 - 777777777
  • 一个11位数字,范围从77700000000 - 77777777777

到目前为止,我似乎工作的是:^7\d{7}|777\d{7}|777\d{9}$

然而,由于我是regex的新手,我想确认这是否是最有效的方式。

提前致谢!

6 个答案:

答案 0 :(得分:2)

这对正则表达式来说不是问题。 正则表达式用于匹配模式,而不是评估数值。

获取用户输入,然后将其与数值进行比较。

$ok =
    ($n >= 7000000 && $n <= 7999999) 
    ||
    ($n >= 777000000 && $n <= 777777777)
    ||
    ($n >= 77700000000 && $n <= 77777777777);

正则表达不是一个魔杖,你会在每个涉及字符串的问题上挥手。

最后,在“正常工作”之前,不要担心“效率最高”。

答案 1 :(得分:1)

您最好的选择是使用^(7\d{6}|777\d{6}|777\d{8})$捕获完整数字字符串,然后将其评估为数字(这假设7,9或11位数字是整个输入)。

答案 2 :(得分:1)

不正确

  1. 由于|的连接优先级较低,因此您的模式被解析为:

    ^7\d{7}
    |
    777\d{7}
    |
    777\d{9}$
    

    锚点仅适用于第一个和最后一个子模式。

  2. 另一件事是“7位数字,范围从7000000 - 7999999”意味着它有 6 个免费数字,而不是指定7\d{7}的7个。其他子模式的相同的一个错误。

  3. 由于您在777000000 - 777777777范围内禁用了777999999,因此您的正则表达式将不如777\d{6}那么方便(如果您想使用正则表达式执行所有操作)。

    要匹配范围777000000 - 777777777,您需要:

    777(?:[0-6]\d{5}|7(?:[0-6]\d{4}|7(?:[0-6]\d{3}|7(?:[0-6]\d{2}|7(?:[0-6]\d|7[0-7])))))
    

    它匹配前缀777,然后是后缀(按顺序):

    • 000000 - 699999
    • 700000 - 769999
    • 770000 - 776999
    • 777000 - 777699
    • 777700 - 777769
    • 777770 - 777777

    (我假设您要匹配777000009)

  4. 解决方案

    修复第一个和第二个问题很简单,只是非捕获组(?:pattern)并调整重复次数:

    ^(?:7\d{6}|777\d{6}|777\d{8})$
    

    然而,单独使用正则表达式解决第3个问题并不容易(可能,但最终会出现一堆代码)。

    正如所建议的那样,将文本解析为数字并使用它会更容易。 11位数可以适合64位整数类型(如果可能,使用整数类型)或双精度浮点(如果使用JavaScript,则数字由双精度浮点表示,具有53位精度)。

答案 3 :(得分:1)

鉴于浮点数和条件数不能很好地混合,
这是一个应涵盖所有目标范围的正则表达式:

^(?:7\d{6}|(?:777[0-6]\d{7}|7777[0-6]\d{6})|(?:(?:77)?(?:777[0-6]\d{5}|7777[0-6]\d{4}|77777[0-6]\d{3}|777777[0-6]\d{2}|7777777[0-6]\d|77777777[0-7])))$

扩展

 ^ 
 (?:
      7 \d{6} 
   |  

      (?:
           777 [0-6] \d{7} 
        |  7777 [0-6] \d{6} 
      )
   |  
      (?:
           (?: 77 )?
           (?:
                777 [0-6] \d{5} 
             |  7777 [0-6] \d{4} 
             |  77777 [0-6] \d{3} 
             |  777777 [0-6] \d{2} 
             |  7777777 [0-6] \d 
             |  77777777 [0-7] 
           )
      )
 )
 $

答案 4 :(得分:0)

这不会起作用吗?

^(?=7[0-9]{6}$|777[0-7]{6}$|777[0-7]{8}$).+

答案 5 :(得分:0)

做这样的事情并不简单,因为地方[n]上允许的数字取决于地方[n-1]上的数字。

考虑范围7000-777。

  • 第一个数字只能是7
  • 第二个可以是[0-6]和其他[0-9]或
    • 其次是7和:
      • 第三个是[0-6]和第四个[0-9]或
        • 第三是7,第四是[0-7]

这将是这样的:

7(([0-6][0-9]{2})|(7(([0-6][0-9])|(7[0-7]))))

让我们测试一下(JavaScript):

var regexStr = '7(([0-6][0-9]{2})|(7(([0-6][0-9])|(7[0-7]))))'
var str = ['7008','7777','7798','7584','7689','7784']
for (var i=0;i<str.length;i++){
var regex = new RegExp(regexStr)
  console.log(regex.exec(str[i]))
}

你拥有的数字越多,正则表达式就越大。我找不到任何其他方法来实现regex中的整数比较...