最新手机号码正则表达式

作者: ROB_YONG | 来源:发表于2015-08-06 16:18 被阅读88890次

    最近项目需要本地检测手机号码正确性,于是用了一段代码,但是后来发现这个代码块已经过时了。在网上简单找了下,发现没有最新的一个公开代码,可能很多人都是用的下面正则方法来检测手机号码,那你们该更新代码了。众所周知,三大运营商已经增加了不少手机号码字段,还用之前的代码就会流失部分用户了。(只讨论国内坏境)

    于是我在网上查了些数据,在之前的代码基础上改了下,方便适用于现在的环境。

    所用方法依然还是正则表达式,正则表达式主要就是用一个公式来匹配字符串是否具备某类规则。我们这里的思路和之前也是一样,只是对之前方法的一个补充与解析。新的方法只匹配了手机号码字段前三位,有些朋友可能还不太懂这个方法,为了方便大家使用,在最后会为大家简单拆分该方法,相信大家很快就会灵活应用了。

    旧的正则表达式代码:

    - (BOOL)isMobileNumber:(NSString *)mobileNum
    {
        /**
         * 手机号码
         * 移动:134,135,136,137,138,139,147,150,151,152,157,158,159,170,178,182,183,184,187,188
         * 联通:130,131,132,145,152,155,156,1709,171,176,185,186
         * 电信:133,134,153,1700,177,180,181,189
         */
        NSString * MOBILE = @"^1(3[0-9]|4[57]|5[0-35-9]|7[01678]|8[0-9])\\d{8}$";
        /**
         * 中国移动:China Mobile
         * 134,135,136,137,138,139,147,150,151,152,157,158,159,170,178,182,183,184,187,188
         */
        NSString * CM = @"^1(3[4-9]|4[7]|5[0-27-9]|7[0]|7[8]|8[2-478])\\d{8}$";
        /**
         * 中国联通:China Unicom
         * 130,131,132,145,152,155,156,1709,171,176,185,186
         */
        NSString * CU = @"^1(3[0-2]|4[5]|5[56]|709|7[1]|7[6]|8[56])\\d{8}$";
        /**
         * 中国电信:China Telecom
         * 133,134,153,1700,177,180,181,189
         */
        NSString * CT = @"^1(3[34]|53|77|700|8[019])\\d{8}$";
        /**
         * 大陆地区固话及小灵通
         * 区号:010,020,021,022,023,024,025,027,028,029
         * 号码:七位或八位
         */
        // NSString * PHS = @"^0(10|2[0-5789]|\\d{3})\\d{7,8}$";
        
        NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE];
        NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM];
        NSPredicate *regextestcu = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU];
        NSPredicate *regextestct = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT];
        
        if (([regextestmobile evaluateWithObject:mobileNum] == YES)
            || ([regextestcm evaluateWithObject:mobileNum] == YES)
            || ([regextestct evaluateWithObject:mobileNum] == YES)
            || ([regextestcu evaluateWithObject:mobileNum] == YES))
        {
            return YES;
        }
        else
        {
            return NO;
        }
    }
    

    新版正则表达式代码:

    + (BOOL)isMobileNumber:(NSString *)mobileNum
    {
        if (mobileNum.length != 11)
        {
            return NO;
        }
        /**
         * 手机号码: 
         * 13[0-9], 14[5,7, 9], 15[0, 1, 2, 3, 5, 6, 7, 8, 9], 17[0-9], 18[0-9]
         * 移动号段: 134,135,136,137,138,139,147,150,151,152,157,158,159,170,178,182,183,184,187,188
         * 联通号段: 130,131,132,145,155,156,170,171,175,176,185,186
         * 电信号段: 133,149,153,170,173,177,180,181,189
         */
        NSString *MOBILE = @"^1(3[0-9]|4[579]|5[0-35-9]|7[0-9]|8[0-9])\\d{8}$";
        /**
         * 中国移动:China Mobile
         * 134,135,136,137,138,139,147,150,151,152,157,158,159,170,178,182,183,184,187,188
         */
        NSString *CM = @"^1(3[4-9]|4[7]|5[0-27-9]|7[08]|8[2-478])\\d{8}$";
        /**
         * 中国联通:China Unicom
         * 130,131,132,145,155,156,170,171,175,176,185,186
         */
        NSString *CU = @"^1(3[0-2]|4[5]|5[56]|7[0156]|8[56])\\d{8}$";
        /**
         * 中国电信:China Telecom
         * 133,149,153,170,173,177,180,181,189
         */
        NSString *CT = @"^1(3[3]|4[9]|53|7[037]|8[019])\\d{8}$";
        
        
        NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE];
        NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM];
        NSPredicate *regextestcu = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CU];
        NSPredicate *regextestct = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CT];
    
        if (([regextestmobile evaluateWithObject:mobileNum] == YES)
            || ([regextestcm evaluateWithObject:mobileNum] == YES)
            || ([regextestct evaluateWithObject:mobileNum] == YES)
            || ([regextestcu evaluateWithObject:mobileNum] == YES))
        {
            return YES;
        }
        else
        {
            return NO;
        }
    }
    
    下面我们简单拆分上面方法,来应对不同的需求

    如果只是简单匹配是否是 手机号码,并不需要上面那么多行代码,可以简单写成这样:

    NSString *MOBILE = @"^1(3[0-9]|4[57]|5[0-35-9]|7[0135678]|8[0-9])\\d{8}$";
    NSPredicate *regextestmobile = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", MOBILE];
    return [regextestmobile evaluateWithObject:mobileNum];
    

    如果你需要匹配是否是 移动/联通/电信 手机号。
    判断移动手机号就是这样:

    + (BOOL)isChinaMobile:(NSString *)phoneNum
    {
        NSString *CM = @"^1(3[4-9]|4[7]|5[0-27-9]|7[08]|8[2-478])\\d{8}$";
        NSPredicate *regextestcm = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM];
        return [regextestcm evaluateWithObject:phoneNum];
    }
    

    相信细心的朋友,应该已经明白了。判断联通手机号,只要把我们的正则字符串改成上面判断联通手机号的字符串就可以了。判断哪种就改变正则表达式就可以了

    ok,在这个基础上,我们还可以组合来判断具体是哪个运营商的手机号,代码如下:

    + (NSString *)getPhoneNumType:(NSString *)phoneNum
    {
        return [self isChinaMobile:phoneNum]? @"中国移动": ([self isChinaUnicom:phoneNum]? @"中国联通":([self isChinaTelecom:phoneNum]? @"中国电信": @"未知"));
    }
    

    主要方法都已公布,至于swift或者其他语言代码块就不一一放上来了,真让我都写,我也不一定都会。。。哈哈哈,核心正则表达式,都是可以用的,拿着代入进去就ok了。

    最后如果发现问题,请告诉我,方便我及时进行修改。(感谢 @联通企业平台-专家客户 提供的数据)


    2016-08-15 修改更新手机匹配字段,包括171,170等虚拟字段

    因为虚拟号码增加太快,对于170号段我这里已经放开了,并没有精确到是哪个运营商。只要170号段的号码都能过。

    大家如果不是要求那么精准的话,可以使用 流刃若火泣 的正则表达式: ^1(3|4|5|7|8)[0-9]\d{8}$


    2017-12-04 修改17x等虚拟号段

    对于17x号段彻底放开,并没有精确到是哪个运营商。只要17开头的号段的号码都能过。
    在网上看到个网址,据说每月都更新,可以自测一下。如果需要精准号码是何运营商,可以根据此网址来修改对应正则表达式
    http://www.xeasy.net/mobile/register.php

    感谢每一位评论者的意见与建议,thanks

    相关文章

      网友评论

      • 谈daxia:太厉害了,好棒!
      • 62b9b63e1d3b:^1(3[0-9]|4[57]|5[0-35-9]|7[01678]|8[0-9])\\d{8}$ 是不是多了个\啊?
        ROB_YONG:@梧桐梦 这是oc语法的问题。oc需要转义,你是用swift?
        62b9b63e1d3b:@ROB_YONG 这个\d不需要转义吧,转义后单纯的指\d。而且在在线正则表达式测试工具中这段正则是检测不出电话号码的,去掉\后是可以监测到的,你可以试试!
        ROB_YONG:@梧桐梦 没有呀。可以用的。第一个\是转义,第二个\d是表示0-9的数字
      • e7574a3af487:验证手机号的那个正则写错了,应该是/^1(3|4|5|7|8)\d{9}$/
        ROB_YONG:@e7574a3af487 :是的。他的 [ 写错了。已修正 :+1: :+1: :+1:
      • 0488cf32d504:如何实现对最后7位或8位一样数字的过滤 如00000000 11111111 这种的
      • Shaun_lan:很强大的正则表达式
        ROB_YONG:@Shaun_lan 谢谢 :blush: :blush:
      • 喵喵炭:mark!
      • 印第安的老斑鸠:前面有 +86 呢?
      • 岚风的叶子:159 4713 0645 这个内蒙古移动的过不了,为什么
        ROB_YONG:@子不语黄昏 如果是这样的话,我也觉得很奇怪了…
        岚风的叶子:不是,我测试的时候没有空格的,真的好奇为什么会通不过
        ROB_YONG:@子不语黄昏 15947130645中间没有其他字符间隔就可以,有间隔暂时没有做这个处理。可以先处理字符串后再匹配
      • 68ae6651f2b0:还有问题 170段的手机号 十三个运营商共享的,具体如下。
        联通 /^170[7-9]\d{7}$/
        电信 /^1700\d{7}$/
        移动 /^1705\d{7}$/
      • 李大戮:可以继续更新下带分隔符的 :smirk:
        李大戮:@ROB_YONG 带分隔符的,例如 135-1313-1313这种
        ROB_YONG:@李大戮 :fearful:没有看到…应该没有错误了吧
      • 我不讲道理的:我正确的移动号码严重失败了,把\\\\换成\\就可以正常严重了。
        我不讲道理的:@ROB_YONG 现在才发现打错字了,惭愧惭愧。
        ROB_YONG:@我不讲道理的 我发现了是 我用手机去编辑这个文章时,\会多加一个\。其实只有两个\的
      • 31e4be245ecf:我验证自己手机号 居然是非法的,不通过唉
        ROB_YONG:@CodeIsLife 已经更改了。现在可以用了。原因是之前用App编辑了这篇文章,然后 \ 自动重复了。15楼有同样的问题
        31e4be245ecf:@ROB_YONG 1313775
        ROB_YONG:@CodeIsLife 多少号段的?
      • 管家頗:没有173啊
        ROB_YONG:@表歌 谢谢。是的:sweat::sweat::sweat:又加了号段…
      • mugbya:请更新: ^1[3|4|5|7|8][0-9]\d{8}$

        8} 后面多了个 ]
        067d67870351:@ROB_YONG 这个包含173 ,,tks :+1:
        067d67870351:@ROB_YONG 这个包含173 ,,tks :+1:
        ROB_YONG:@2444a1d96cc0 :+1:是的。tks
      • 请叫我留胡渣:居然有这么多的电话开头
      • 7e5ed2c6e212:171的没有。。。
        ROB_YONG:@孙长老快收了神通吧 百度找的:joy::joy::joy:是的,太不方便了。我现在的做法是尽量放开客户端本地检验。服务器那边如果有需求要精准到运营商的,可以精准点。因为官方查询渠道不清楚在哪…所以人为的间断性去关注那些号段更新信息:joy::joy:
        7e5ed2c6e212:@ROB_YONG :pray: 大神 我想问一下 这些号段是去移动 联通官网 :kissing_heart: 找的吗? 如果有新号段 APP更新不及时的话 用户体验就变差 挺不好的~
        ROB_YONG:@孙长老快收了神通吧 :+1: 已更新
      • 飘飘然的影子:大兄弟,电信那个好像没有用啊。。。。
        ROB_YONG:@飘飘然的影子 兄弟,可以用的。刚调整了下表达式,修改了虚拟号码的判断。至于电信号段单独拼配,我刚刚也试了下,可以的。不知道你遇到的是什么问题
      • 95c9800fdf47:楼主能不能把你的所有正则表达式的方法公开下,来个git demo!多谢!
      • 来宝:能判断归属地不,嘻嘻
        ROB_YONG:@来宝 :smile:暂时不能…数据量太大,需要有详细准确的资料才能做
      • 孟辉__梦笔生花:这个适用虚拟手机号吗 比如小米手机卡 和阿里手机卡???
        ROB_YONG:@JayRierWolf 用文章里的表达式包含了173,文章之前有更新。评论里的这个没有
        067d67870351:@ROB_YONG 兄弟173 ,没有
        ROB_YONG:@孟辉梦笔生花 支持的。
        NSString *MOBILE = @"^1(3[0-9]|4[57]|5[0-35-9]|8[0-9]|70)\\d{8}$";
        这里校验了所有170字段的虚拟手机号
      • fa514728b42a::+1: 挺全的,谢谢作者。不过还是有点瑕疵:*MOBILE那里,表达式汇总的还不够全,没有把176、177、178也弄进来。
        这是我改的,还不清楚实用性: NSString *MOBILE = @"^1((3[0-9]|4[57]|5[0-35-9]|7[0678]|8[0-9])\d{8}$)
        流刃若火泣:这个正则在我输入 号码15311112222 后,崩了,报错是,2016-04-20 16:38:08.519 Sss[6001:2707638] UMLOG: error: session_id=ABC5D2B72486953B2922AC454488C191, context=Can't do regex matching, reason: Can't open pattern U_REGEX_MISMATCHED_PAREN (string 15311112222, pattern ^1((3[0-9]|4[57]|5[0-35-9]|7[0678]|8[0-9])\d{8}$, case 0, canon 0)
        为啥?

        流刃若火泣:兄弟 你这个很全啊!
        ROB_YONG:@George_Windy 有的。可以搜索到。注释里都标注了。
      • 努力微笑:没有看到 170 号段
        ROB_YONG:@努力微笑 👍非常感谢您的意见,虽然是虚拟号码,但确实有人用。下午马上修改

      本文标题:最新手机号码正则表达式

      本文链接:https://www.haomeiwen.com/subject/jqcbqttx.html