驗證手機號碼格式的正則表達式編寫思路詳解

1、獲取目前中國三大運營商的手機號碼段

號碼段地址
圖片描述正則表達式


如上圖咱們能夠根據不一樣運營商的號碼段來編寫正則,也能夠進行統一校驗的編寫,我這邊主要是編寫統一校驗的。編程

2、思路

一、爲了獲得號碼段的規律,咱們能夠把它們先進行排序一下,排序代碼以下:

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");
          }

排序結果:
排序結果緩存


二、由上面的排序結果能夠看出,規律仍是挺明顯的,首先咱們來看一下

13開頭:
130 131 132
133 134 135 136 137 138 139
對應正則爲:(13[0-9]\d{8})工具


14開頭:145 147 對應正則爲:(14[57]\d{8})性能


15開頭:
150 151 152
153 155 156 157 158 159
對應正則爲:(15[0-35-9]\d{8})優化


17開頭:173 176 177 178 對應正則 爲:(17[36-8]\d{8})spa


18開頭:180 181 182 183 184 185 186 187 188 189
對應正則爲:(18[0-9]\d{8})3d


170開頭:1700 1705 1707 1708 1709 對應正則爲:(170[057-9]\d{7})code


三、把上面的正則用或符號(|)拼在一塊兒,就是一個完整的校驗手機號的正則表達式了,以下

(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})blog

但此時,咱們仍是能夠看出一些規律能夠來簡化這個正則表達式,相似初中數學的合併同類項,把\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})

四、優化

上面這個正則表達式已經能夠投入編程使用了,但這個這個正則表達式分組有點多,獲取捕獲組的個數:

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個分組
圖片描述

五、結果

最終咱們獲得的正則表達式爲
(?:(?:(?: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})$


固然,若是不須要準確校驗的話,其實能夠這麼寫就夠了,以下:^1\d{10}$

相關文章
相關標籤/搜索