【问题标题】:Telephone number regex all formats电话号码正则表达式所有格式
【发布时间】:2021-03-19 17:58:21
【问题描述】:

我正在开发一个表达式来验证所有可能的电话号码格式。我有 50%,它没有通过 * . - whitespace 验证我承认的字符

这些是规则

它可以包含左括号和右括号 ex。 (55)

它可以连续或不'+' char ex。 (+52)

它可以在括号内包含 2 或 3 个数字 ex。 (+555) o (+55)

它可以在右括号和下一个之间包含空格 数字前。 (55) 44332211

括号中的连续数字必须是 6 或 8 个数字,例如。 (55)443322 或 (55)44332211

括号中的连续数字可以包含空格, 破折号、星号或冒号。例如(55)44-33-22-11 o (55)44 33 22 11 o (55)44*33*22*11 o (55)44.33.22.11

括号中的连续数字可以分成几组 2、3 或 4 个数字,例如。 (55)5544-3322 o (55)55 44 33 22 o (555)444*333

数字格式可以是一行 8、10 或 12 个数字,例如。 55443322 o 5544332211 o 554433221100

这是正则表达式

[\(]?[\+]?(\d{2}|\d{3})[\)]?[\s]?((\d{6}|\d{8})|(\d{3}[\*\.\-\s]){3}|(\d{2}[\*\.\-\s]){4}|(\d{4}[\*\.\-\s]){2})|\d{8}|\d{10}|\d{12}

这是正则表达式的映射

我做错了什么?我留下一个示例脚本,我正在为 Python 做的正则表达式,我不知道我是否用 JS 改变了很多

$(function(){

  $('ul li').each(function(){
    let number = $(this).text();
    let regex = /^[\(]?[\+]?(\d{2}|\d{3})[\)]?[\s]?((\d{6}|\d{8})|(\d{3}[\*\.\-\s]){3}|(\d{2}[\*\.\-\s]){4}|(\d{4}[\*\.\-\s]){2})|\d{8}|\d{10}|\d{12}$/;
    let res = regex.test( number );
    $(this).text( $(this).text() + ' is: ' + res);
  });

})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Telephone numbers
<ul>
  <li>test</li>
  <li>(55)test</li>
  <li>(55)333-test</li>
  <li>(55)test 22</li>
  <li>554433221100</li>
  <li>5544332211</li>
  <li>55443322</li>
  <li>(55)443322</li>
  <li>(55)44332211</li>
  <li>(+55)443322</li>
  <li>(+55)44332211</li>
  <li>(55)4433*2211</li>
  <li>(55)444.333</li>
  <li>(55)44-33-22-11</li>
  <li>(55)4433-2211</li>
  <li>(+55)443 322</li>
</ul>

【问题讨论】:

  • 这是否意味着你所有的测试用例都应该返回true
  • 只有在规则指定的情况下,por example (55)test 是不允许的,但是 55-44-33-22-11 是的(并且它不起作用:()
  • @AlbertoSiurob 你的规则有很多漏洞。是否允许 (55)123-4567555-123-456755-1234-56+55123456551-234-567(其中 55 是国际代码)?
  • 这是一个例子,可以以(32)开头 55是我的区号
  • @AlbertoSiurob 是的,但是这些示例的结果应该是什么?另外,5555*5555*555555 12-12-1255 123-123 呢?

标签: python regex


【解决方案1】:

你可以使用

^(?:\d{8}(?:\d{2}(?:\d{2})?)?|\(\+?\d{2,3}\)\s?(?:\d{4}[\s*.-]?\d{4}|\d{3}[\s*.-]?\d{3}|\d{2}([\s*.-]?)\d{2}\1\d{2}(?:\1\d{2})?))$

请参阅regex demo

详情

  • ^ - 字符串开头
  • (?: - 外部分组结构的开始:
    • \d{8} - 8 位数字
    • (?:\d{2}(?:\d{2})?)? - 可选的 2 位数字,后跟可选的 2 位数字子字符串(因此,可以匹配 8、10 或 12 位数字字符串)
  • | - 或

    • \( - 一个(
    • \+? - 1 或 0 个加号
    • \d{2,3} - 2 位或 3 位数字
    • \) - 一个 ) 字符
    • \s? - 1 或 0 个空格
    • (?: - 分组:
      • \d{4} - 4 位数字
      • [\s*.-]? - 空格、*.-,可选出现
      • \d{4} - 4 位数字
    • | - 或
      • \d{3}[\s*.-]?\d{3} - 3 位数字,一个分隔符,3 位数字
    • | - 或

      • \d{2}([\s*.-]?)\d{2}\1\d{2}(?:\1\d{2})?:2 位,捕获到第 1 组的分隔符,2 位,与第 1 组中相同的分隔符,2 位,以及与第 1 组中相同的分隔符和两位数字的可选序列
    • ) - 内部分组结束。

  • ) - 外部分组结束
  • $ - 字符串结束。

【讨论】:

  • 美丽、真棒和详细。谢谢老师
  • 我不会打开另一个线程,只是为了结束这个,你能告诉我当号码是 +55 52 4433 2211 或 5522 3030 时如何验证?
  • 你是个怪物!一辆装满啤酒的卡车正开往你家。谢谢
【解决方案2】:

另一种可能的解决方案(可能更容易)是在源头简单地验证电话号码,然后在服务器端只允许这种格式。

(function(){
  "use strict";
  var removeNonPhoneNumber = /\D/g;

  function formatPhoneNumber(ownSection, restOfIt){
    var newOwnSection = ownSection.replace(removeNonPhoneNumber, "");
    var newRestOfIt = restOfIt.replace(removeNonPhoneNumber, "");
    var totalLength = newOwnSection.length + restOfIt.length |0;

    var i=0, res="";
    if (totalLength > 10) {
      // includes country code
      for (; i < (totalLength - 10|0) && i < newOwnSection.length; i=i+1|0)
        res += newOwnSection.charAt(i);
      res += '-';
    }
    if (totalLength > 7) {
      // includes area code
      for (; i < (totalLength - 7|0) && i < newOwnSection.length; i=i+1|0)
        res += newOwnSection.charAt(i);
      res += '-';
    }
    if (totalLength > 4) {
      // includes local code
      for (; i < (totalLength - 4|0) && i < newOwnSection.length; i=i+1|0)
        res += newOwnSection.charAt(i);
      res += '-';
    }
    for (; i < totalLength && i < newOwnSection.length; i=i+1|0)
      res += newOwnSection.charAt(i);
    return res;
  }
  function autoStretch(evt){
    var target = evt && evt.target;
    if (!target) return;
    if (
      target.getAttribute("type") === "tel" && (
        // If selectionStart is supported OR the user is deselecting
          // the input, then validate
        typeof target.selectionStart === "number" ||
        evt.type === "blur"
      )
    ) {
      // forceful tel validation. It normalizes the number to be pretty
      var valueNow = target.value;
      var sStart=target.selectionStart|0, sEnd=target.selectionEnd|0;

      var newValue = formatPhoneNumber(valueNow, "");
      if (valueNow !== newValue) {
        target.value = newValue;

        // now properly shift around the cursor positions:
        if(typeof target.selectionStart==="number") 
          target.selectionStart = formatPhoneNumber(
            valueNow.substring(0, sStart), valueNow.substring(sStart)
          ).length|0;
        if(typeof target.selectionEnd==="number") 
          target.selectionEnd = formatPhoneNumber(
            valueNow.substring(0, sEnd), valueNow.substring(sEnd)
          ).length|0;
      }
    }
    target.style.width = '';
    target.style.width = target.scrollWidth + 'px';
  }

  var teleInputs = document.getElementsByClassName("prevent-invalid-telephone");
  for (var i=0, hookOptions={"passive":1}; i<teleInputs.length; i=i+1|0) {
    teleInputs[i].addEventListener("input", autoStretch, hookOptions);
    teleInputs[i].addEventListener("change", autoStretch, false);//for IE
  }
})();
Enter your telephone here: &lt;input type="tel" autocomplete="tel-area-code" pattern="([0-9]+-)?[0-9]{3}-[0-9]{3}-[0-9]{4}" aria-label="Your telephone number" class="prevent-invalid-telephone"/&gt;

上面的 sn-p 可能看起来很长,但请放心,缩小后它会下降到区区 1008 字节(应用 zopfli gzip 后只有 486 字节)。

!function(){"use strict";function h(c,b){var d=c.replace(/\D/g,"")
b.replace(/\D/g,"");var e=d.length+b.length|0,a=0,f=""
if(10<e){for(;a<(e-10|0)&&a<d.length;a=a+1|0)f+=d.charAt(a)
f+="-"}if(7<e){for(;a<(e-7|0)&&a<d.length;a=a+1|0)f+=d.charAt(a)
f+="-"}if(4<e){for(;a<(e-4|0)&&a<d.length;a=a+1|0)f+=d.charAt(a)
f+="-"}for(;a<e&&a<d.length;a=a+1|0)f+=d.charAt(a);return f}function
l(c){var b=c&&c.target;if(b){if("tel"===b.getAttribute("type")&&("number"==typeof
b.selectionStart||"blur"===c.type)){c=b.value;var
d=b.selectionStart|0,e=b.selectionEnd|0,a=h(c,"")
c!==a&&(b.value=a,"number"==typeof b.selectionStart&&(b.selectionStart=h(
c.substring(0,d),c.substring(d)).length|0),"number"==typeof
b.selectionEnd&&(b.selectionEnd=h(c.substring(0,e),c.substring(e)).length|0))}
b.style.width="";b.style.width=b.scrollWidth+"px"}}for(var
k=document.getElementsByClassName("prevent-invalid-telephone"),g=0;g<k.length;g=g+1|0)
k[g].addEventListener("input",l,{passive:1}),k[g].addEventListener("change",l,!1)}();
Enter your telephone here: &lt;input type="tel" autocomplete="tel-area-code" pattern="([0-9]+-)?[0-9]{3}-[0-9]{3}-[0-9]{4}" aria-label="Your telephone number" class="prevent-invalid-telephone"/&gt;

【讨论】:

    【解决方案3】:

    接受的答案有很多缺陷:

    • \s 不仅适用于空白字符,也适用于 \r 和 \n。

      +11 1111
      1111
      #This matches
      
    • 数字的最小位数为 8,最大为 12,但这些数字与国际前缀数字无关:

      (+39)333 333 # 6 digits: this matches but it is not valid  
      (+39)3333 3333 3333 # 12 digits: this is valid but it does not match
      
    • 国际前缀仅在括号之间匹配

      +39 3475 4087 18 # this is valid but doesn't match
      
    • 正则表达式并非琐碎、冗长、复杂和无缘无故的错误。

    我做了这个来克服这些缺陷并改进它:

    ^(?:((\+?\d{2,3})|(\(\+?\d{2,3}\))) ?)?(((\d{2}[\ \-\.]?){3,5}\d{2})|((\d{3}[\ \-\.]?){2}\d{4}))$
    

    通过接受的答案中提供的良好解释,应该相对容易理解这一点。

    这是live demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-23
      • 1970-01-01
      • 2016-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-23
      • 2014-02-15
      相关资源
      最近更新 更多