验证手机号码格式的正则表达式编写思路详解

Cooking Regex微信公众号
正则表达式学习

 

一、获取目前中国三大运营商的手机号码段

 
 
如上图我们可以根据不同运营商的号码段来编写正则,也可以进行统一校验的编写,我这边主要是编写统一校验的。
 

二、思路

1、为了得到号码段的规律,我们可以把它们先进行排序一下,排序代码如下:

		  int[] phoneHead={134,135,136,137,138,139,182,183,187,188,152,157,158,159,150,147,184,151,178,1705
				  ,130,131,132,155,156,186,145,185,1709,1707,1708,176
				  ,133,153,180,181,189,177,1700,173};
		  
		  Arrays.sort(phoneHead);
		  for(int head:phoneHead){
			  System.out.print(head+"\t");
		  }
	   

排序结果:

2、由上面的排序结果可以看出,规律还是挺明显的,首先我们来看一下,

 
13开头:130 131132 133134 135136 137138 139     对应正则为:(13[0-9]\d{8})
 
14开头:145 147  对应正则为:(14[57]\d{8})
 
15开头:150 151152 153155 156157 158159 对应正则为:(15[0-35-9]\d{8})
 
17开头:173 176177 178     对应正则 为:(17[36-8]\d{8})
 
18开头:180 181182 183184 185186 187188 189对应正则为:(18[0-9]\d{8})
 
170开头:1700 1705 1707 1708 1709 对应正则为:(170[057-9]\d{7})
 

3、把上面的正则用或符号(|)拼在一起,就是一个完整的校验手机号的正则表达式了,如下

 
(13[0-9]\d{8})|(14[57]\d{8})|(15[0-35-9]\d{8})|(17[36-8]\d{8})|(18[0-9]\d{8})|(170[057-9]\d{7})
 
但此时,我们还是可以看出一些规律可以来简化这个正则表达式,类似初中数学的合并同类项,把\d{8}提取出来,简化为:
((13[0-9])|(14[57])|(15[0-35-9])|(17[36-8])|(18[0-9]))\d{8}|(170[057-9]\d{7})
为了更明显的查看分组,我们可以用分组括号把((13[0-9])|(14[57])|(15[0-35-9])|(17[36-8])|(18[0-9]))\d{8}包含起来,变为:
(((13[0-9])|(14[57])|(15[0-35-9])|(17[36-8])|(18[0-9]))\d{8})
于是,完整的正则就变为了:
(((13[0-9])|(14[57])|(15[0-35-9])|(17[36-8])|(18[0-9]))\d{8})|(170[057-9]\d{7})
 

4、优化

上面这个正则表达式已经可以投入编程使用了,但这个这个正则表达式分组有点多,获取捕获组的个数:
 String regex="(((13[0-9])|(14[57])|(15[0-35-9])|(17[36-8])|(18[0-9]))\\d{8})|(170[057-9]\\d{7})";
		   Matcher m=Pattern.compile(regex).matcher("");
		   System.out.println(m.groupCount());

可以得到8个分组,但如果我们只是用来校验的话,直接用非捕获组就可以了,这样可以提高一些性能。
提示:()捕获组会把匹配到的数据缓存起来,(?:)非捕获组不会缓存匹配到的数据。
借助正则工具,我们可以很清晰得看到分组的情况:
改为非捕获组后,正则变为:(?:(?:(?:13[0-9])|(?:14[57])|(?:15[0-35-9])|(?:17[36-8])|(?:18[0-9]))\d{8})|(?:170[057-9]\d{7})
此时在RegexBuddy正则工具上可以看到0个分组
 

5、结果

最终我们得到的正则表达式为
(?:(?:(?:13[0-9])|(?:14[57])|(?:15[0-35-9])|(?:17[36-8])|(?:18[0-9]))\d{8})|(?:170[057-9]\d{7})
若是要匹配开头和结尾的话,改为
^(?:(?:(?:13[0-9])|(?:14[57])|(?:15[0-35-9])|(?:17[36-8])|(?:18[0-9]))\d{8})|(?:170[057-9]\d{7})$
 
 
 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值