【问题标题】:Regex to exclude same-digit delimited phone numbers excludes all phone numbers正则表达式排除相同数字分隔的电话号码排除所有电话号码
【发布时间】:2018-01-09 22:36:45
【问题描述】:

我一直在使用正则表达式:

/^(\d)(?!\1{2}\1{3}\1{4}$)\d{2}\d{3}\d{4}$/

不包括所有数字相同的 10 位电话号码,例如 22222222223333333333

现在,我需要正则表达式来排除格式为 222-222-2222333-333-3333 的相同数字电话号码。

这是我为了允许分隔符而尝试的修改后的正则表达式:

/^\((\d)(?!\1{2}-\1{3}-\1{4}$)\d{2}\)\d{3}-\d{4}$/

很遗憾,它排除了所有个电话号码。我哪里出错了?

【问题讨论】:

  • 您是否受限于使用正则表达式?因为使用其他 JS 技术会更容易、更灵活。

标签: javascript regex


【解决方案1】:

要匹配 10 位电话号码 phonenumber 但如果它们都是相同的数字,例如 2222222222222-222-2222 则排除,您可以将正则表达式更改为:

^(\d)(?!\1{9})(?!\1{2}-\1{3}-\1{4})\d{2}(-?)\d{3}\2\d{4}$

说明

  • 从字符串^开始
  • 匹配捕获组中的第一个数字(\d)
  • 一个否定的前瞻,它断言后面的数字不是同一个数字 9 次 (?!\1{9})
  • 一个否定的前瞻,它断言接下来的不是带有连字符(?!\1{2}-\1{3}-\1{4})的模式
  • 通过使用对第二组 \d{2}(-?)\d{3}\2\d{4} 的反向引用来匹配带或不带连字符的数字
  • 字符串结尾$

如果您还想接受 (123)-456-7890 之类的格式,例如可以使用:

^(?!(\d)\(\1{3}\))(?!(\d)\2{9})(?!(\d)\3{2}-\3{3}-\3{4})(?:\(\d{3}\)|\d{3})(-?)?\d{3}\4\d{4}$

【讨论】:

    【解决方案2】:

    您的分隔符版本非常接近。粗略地说*,您只是在前瞻中丢失了),而在实际匹配中丢失了第一个-。 (顺便说一句,第一个$ 也是多余的。)

    假设您希望同时允许123-456-7890 (123)-456-7890,则工作的* 正则表达式为:
    正则表达式 1

    ^\(?(\d)(?!\1{2}\)?-\1{3}-\1{4})\d{2}\)?-\d{3}-\d{4}$
       |            |_|                    ||_
       |             |                     |  |
       |   missed (optional) ')'           | missed '-'
       |                                   |
     '?' required to make '(' and ')' optional
    

    Demo ?


    如果您还希望允许1234567890(123)4567890,则需要将连字符设为可选。请注意,在实际匹配中,您必须使用捕获组和反向引用“链接”两个连字符,否则123-4567890123456-7890 等也会匹配:
    正则表达式 2

    ^\(?(\d)(?!\1{2}\)?-?\1{3}-?\1{4})\d{2}\)?(-)?\d{3}\2\d{4}$
                        |      |              |__|     ||
                     optional hypens           |   back reference to captured hypen
                                               |
                                     optional captured hypen
    

    *警告:

    (123-456-7890123)-456-7890(以及第二个正则表达式的 (1234567890123)4567890)都是允许的。如果您希望排除这些,则在正则表达式的开头需要积极的前瞻 (?=\(\d{3}\)|\d{3}[^)])
    正则表达式 1a

    ^(?=\(\d{3}\)|\d{3}[^)])\(?(\d)(?!\1{2}\)?-\1{3}-\1{4})\d{2}\)?-\d{3}-\d{4}$
     |_____________________||_________________________________________________|
                |                                    |
       positive lookahead                         Regex 1
    

    正则表达式 2a

    ^(?=\(\d{3}\)|\d{3}[^)])\(?(\d)(?!\1{2}\)?-?\1{3}-?\1{4})\d{2}\)?(-)?\d{3}\2\d{4}$
     |_____________________||_______________________________________________________|
                |                                       |
       positive lookahead                            Regex 2
    

    正向预测

    ^(?=\(\d{3}\)|\d{3}[^)])
        |_______| |_______|
            |         |
            |  or starts with 3 digits, then no ")"
            |
    Either starts with "(", then 3 digits, then ")"
    

    【讨论】:

      【解决方案3】:

      试试这个:

      /^(?:(?:(\d)(?!\1)){3}-?){2}(?:(?:(\d)(?!\1)){4})$/
      

      我更喜欢 regexr.com 进行测试。

      说明:

      (?:(?:(\d)(?!\1)){3}-?)
      

      一组 3 位数字,但前提是它们不重复。末尾的单个“-”是可选的。

      以上两个模式必须匹配两次。最后一个模式是相同的,只是它匹配 4 位数字,并且不允许在末尾使用“-”。

      已编辑以修复 11 位和 12 位匹配问题。

      【讨论】:

      • 不幸的是,这个正则表达式还允许使用 xxxx-xxx-xxxxxxxx-xxxx-xxxx 格式的 11 位和 12 位电话号码。它也不允许像(xxx)-xxx-xxxx(xxx)xxx-xxxx 中的()。老实说,这在问题中并不清楚,因为示例指定了xxx-xxx-xxxx,而正则表达式看起来适用于(xxx)xxx-xxxx(xxx)-xxx-xxxx 或两者。
      猜你喜欢
      • 2015-12-21
      • 1970-01-01
      • 2012-04-28
      • 1970-01-01
      • 1970-01-01
      • 2017-09-23
      • 2014-02-15
      • 1970-01-01
      相关资源
      最近更新 更多