正則入門
正則 是個難啃的骨頭,以前看著會正則的人 感覺都好牛逼。於是工作了2年了終於鼓起勇氣啃這個骨頭了。。
例子入手
首先我們先看下相關的字元代表。我們先看這個例子。這個?就是驗證字串是否是數字。
let regex = /^[0-9]+$/;
let number = `123`;
let string = `abc`;
regex.test(number); // true
regex.test(string); // false
複製程式碼
可能很多人這時用到了百度谷歌一下然後複製過去直接用就OK了,但是這樣沉澱不到東西,所以我們來靜下心看看這個正則到底什麼意思,首先我們要了解的是相關的
- ^ :脫字元,匹配開頭,在多行匹配中匹配行開頭,有時也表示求反的概念。
- $ :美元符號, 匹配結尾,在多行匹配中匹配行結尾。
- {m,} 表示至少出現m次。
- {m} 等價於{m,m},表示出現m次。
- +: 等價於{1,},表示出現至少一次。記憶方式:加號是追加的意思,得先有一個,然後才考慮追加。
- *:等價於{0,},表示出現任意次,有可能不出現。記憶方式:看看天上的星星,可能一顆沒有,可能零散有幾顆,可能數也數不過來。
可能這時你有些不理解 [0-9],其實他等價於 [0123456789] ,在正則裡可以縮寫所以為 [0-9], 同理[a-z],[A-Z]也是同樣的道理。為什麼使用正則因為他書寫簡單,我們還可以簡化,讓我們等下看看接下來的這些字元,思考下怎麼繼續簡化。
那我們大概能猜到這個意思代表什麼了,從 開頭(^) 到 結尾($) 0-9([0-9]) 出現 至少一次 (+) , 所以就很好理解了,為什麼這個是驗證數字的想必就能理解了。
接下來我們再來看一些特殊字元:
- d就是[0-9]。表示是一位數字。記憶方式:其英文是digit(數字)。
- D就是[^0-9]。表示除數字外的任意字元。
- w就是[0-9a-zA-Z_]。表示數字、大小寫字母和下劃線。記憶方式:w是word的簡寫,也稱單詞字元。
- W是[^0-9a-zA-Z_]。非單詞字元。
- s是[ v
f]。表示空白符,包括空格、水平製表符、垂直製表符、換行符、回車符、換頁符。記憶方式:s是space character的首字母。
- S是[^ v
f]。 非空白符。
- .就是[^
u2028u2029]。萬用字元,表示幾乎任意字元。換行符、回車符、行分隔符和段分隔符除外。記憶方式:想想省略號…中的每個點,都可以理解成佔位符,表示任何類似的東西。
好的我們看到了 d 其實就是 [0-9],此時忽然恍然大悟,原來上面的正則還能簡化:
let regex = /^d+$/; // /^[0-9]+$/;
複製程式碼
這時我們大概 已經懂得這個正則代表什麼東西了,之後再出現驗證使用者輸入的是不是數字,就別再百度了,分分鐘就寫出來。
舉一反三
我們已經瞭解之前的這個例子後,大概能推敲如何實現驗證全是字母:
let regex = /^[a-z]+$/;
let string = `abc`;
let number = `123`;
regex.test(number); //false
regex.test(string);//true
複製程式碼
正則是區分大小寫字母的,所以,我們要驗證大寫字母的時大概是這樣:
let regex = /^[A-Z]+$/;
let string = `abc`;
let STRING = `ABC`
let number = `123`;
regex.test(number); //false
regex.test(string);//false
regex.test(STRING); //true
複製程式碼
好了我們已經反二了,接下來我們來反三,即是大寫字母又是小寫字母,怎麼去寫?
let regex = /^[a-zA-Z]+$/
複製程式碼
估計到這裡我們都已經算入門了,不是很複雜的正則都可以自己去寫了。
考驗
接下來我們來看一些常用需求:
正則 驗證 手機 。
手機號碼是幾位,emmmm,等下我先數數 183 XXX XXX XX ,噗,11位,好吧當我沒說。那我們分析下,手機號, 首先全部都是數字, 開頭第一位一定是 數字 1 ,然後只要滿足 11位就可以了,我們已經把需求整理清楚了,如果我們用 js 去寫會怎麼寫?我這裡隨意寫一寫,可能有更好的方式
const isPhone = (number) => {
const len = number.length;
if (typeof number !== `string` || len !== 11 || number[0] !== `1`) {
return false;
}
for (let i = 0; i < len; i++) {
if (isNaN(number[i])) return false;
}
return true;
}
console.log(IsPhone(`18367490590`)); //true
複製程式碼
可見一個 js 書寫是多麼麻煩,也可能是我的解決方式不是很牛逼,隨便寫寫,各位有什麼好的解決方案也可以給我評論。。扯遠了。現在我們來看看要是用正則怎麼寫?
let regex = /^1d{10}$/;
複製程式碼
一行程式碼搞定。就是這麼簡單,讓我們分析一下。
- ^ 開頭匹配
- 1 開頭沒毛病
- d 表示 [0-9] 代表必須是數字
- {10} 也是 {10, 10} 表示 [0-9]出現10次,加上1 也就是說 11位。
- $ 結尾匹配沒毛病。
以上一行程式碼就搞定了。很簡便其實分析下也不是很難。
正則 驗證 郵箱 。
我就不寫什麼 js 的版本了,有興趣的同學可以自己嘗試寫寫。我們看看郵箱的正則應該是有這麼幾個需求的:
- xxx@xxx.xxx
- @ 前需要有任意字元
- 郵箱 有 @ 符號。
- @後有任意字元
- 要有 .
- . 後跟任意字元
let regex = /^w+@w+.w+/;
複製程式碼
簡單分析一下:
- w我們知道是[0-9a-zA-Z_]下劃線
- + 代表至少出現一次 好比 {1,}
- @ 必須需要。
- . 這裡要注意下,因為 . 是特殊正則字元, 代表萬用字元, 我們這裡需要的是 “.” 字串,所以加了 進行轉譯
補充案例
之前的例子們大概動了一些東西,讓我們再來看幾個例子。
匹配16進位制顏色值
大概是這樣:
#ffbbad
#Fc01DF
#FFF
#ffE
寫法:
let regex = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
複製程式碼
分析:
開頭是#號,表示一個16進位制字元,可以用字元組[0-9a-fA-F]。然後 {6} 代表 出現6 次,這時候你可能有點迷
這個代表什麼 稍等引出這個 | 是分支的概念。再說說後面其實也很好理解 字元組[0-9a-fA-F] 出現3次。
- | 分支,其實可以理解為這個是程式設計中的或,很容易理解了。那麼,我們知道或者是惰性的,一個成立不向下執行,這裡其實也一樣。
讓我們再來一個案例:
驗證 匹配 yyyy-mm-dd : 2018-10-20
正則如下:
var regex = /^d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]d|3[01])$/;
複製程式碼
分析一波:
- 年 d{4} [0-9]出現4次。
- 月 共12個月, 十位0的話就是 [1-9]月,十位1的話就是 [0-2]個月。
- 日 最多31天 ,十位0的話就是 [1-9]天,十位1,十位2就是[0-9] 3的話只有0或者1。
結語。
正則是個大工程這裡只是一些簡單的正則,比如還有惰性匹配等 我們還沒有見到, 在後面的系列中我會慢慢的加入進去。未完…