正則系列——JavaScript正則表達式入門心得

我發現有個別字符被這個編輯器給刷掉了,可是灰色區域顯示正常,以灰色區域代碼爲準javascript

什麼玩意?

在我剛開始學習編程的時候,就聽過正則了,也據說正則很牛逼,懂正則的更牛逼。可是苦於沒有人指點,也沒有使用正則的場景,本身看教程又懵逼,直到如今,才發現了入門的訣竅。前端

在不一樣的編程語言中,正則表達式的寫法會有所不一樣,這裏咱們討論的是JavaScript正則寫法。java

學習正則,不要憑空想象,要使用開發工具去測試,推薦你使用在線正則測試網站:https://regex101.com,或者使用瀏覽器控制檯。git

最簡單的正則

正則在天然語言處理中普遍運用到,對前端開發者來講,最多見的正則是表單上的一些驗證。若是你不熟悉正則,在寫表單的時候,是從網上直接搜索某某正則的寫法,而後copy過來。github

可是,在你看完這篇文章以後,我但願你能夠直接寫出一些簡單的正則,再也不須要百度了。面試

如今介紹一種最簡單的正則(匹配指定的文本):
下面是一段美文,咱們如今想把裏面的某個字,好比(),匹配出來。正則表達式

var s = '前世茫茫人海的擦肩,種了此生的碰見,在花海的某一朵間,是你最美的笑顏。繁花三千,只爲一人留戀,幾度春秋,只等你花開的一面。多少來來回回,夢裏若隱若現,舉着思念的酒盞,輕酌夜色微涼,讓回憶的美好舞翩翩。擱淺了時光,靜默緣分的一端,遠處的風景,依然是你微笑的眉眼。'
s.match(/的/g)

咱們使用到了match方法來作匹配,來分析一下這個寫法,s表示字符串,g表示全局匹配,若是去掉g,只能匹配出來第一個()。
是否是最簡單的正則?你須要匹配什麼內容,就直接在//之間寫這個字符,而後正則系統會自動從字符串去查找。
可能這樣說不是很直觀,我奉獻一張101的截圖,特別關注紅框部分,最上邊是正則的輸入框,下面是字符串,右邊是匹配出來的字符:編程

clipboard.png

經常使用正則方法瞭解

上面的例子中,使用到了match(),能夠匹配出來字符,而且返回值是一個數組。還有一個經常使用的方法是test()test的返回值是bool類型,一般用來寫在if語句中判斷一個字符串是否知足正則表達式,在表單驗證中常常用到。還有一個經常使用的方法是replace(),replace和match比較像,都能匹配出字符,可是replace還有第二個參數能夠作字符替換。
下面咱們會講到三個方法的具體使用場景。往下看!segmentfault

test()

正則有各類各樣的符號,通常很難背下來,可是經常使用的符號多練習幾遍,印象就會深入。數組

咱們用實際的例子來分析test()以及正則的實現,以註冊表單爲例:
test()和match()寫法恰好反過來,test是正則寫在前面,字符串寫到函數的參數中。

場景1:帳號只能是數字

看到這樣一道題目,你首先要思考2個字——「規則」,帳號是主體,帳號的規則是隻能是數字,那麼就是說輸入非數字就不能匹配。

瞭解了規則以後,就很簡單了,正則提供了默認匹配數字的字符,d或者是[0-9],那麼是否是直接/d/.test('123')就好了呢?固然不是,d表示是數字,你還須要加上一個特殊字符,表示匹配全部的數字,由於一個字符串有N個數字,所有都要匹配成功。

這裏我使用的是+,加號表示至少匹配一次數字,好比123,若是使用d,就只能一個個匹配出來[1,2,3],這須要在match方法中使用,在test方法中,必須匹配整個字符串是否符合正則。改爲d+以後,匹配的是整個字符串中的數字,是否是離咱們的最終結果很接近了。

上面的操做彷佛已經能夠匹配出數字了,可是記住,test()方法中,若是你要驗證整個字符串只能是數字,必須加上正則的開始符號^和結束符號$,表示的是從字符串'123'開頭匹配到結尾都必須知足數字,若是中間插入其餘字符'1kk2什麼3',就匹配失敗。因此最終的正則寫法是 /^\d+$/,或者是/^d+$/g,這裏的g可加可不加。

var user = '123' //能夠把123改爲任意字符來測試。
if (/^\d+$/g.test(user)) {} //寫法1 if(true){}
if (/^[0-9]+$/g.test(user)) {} //寫法2 if(true){}

場景2:帳號只能是字母

數字匹配完了,換成字母會不會呢?只要把d或[0-9]改爲字母的正則就好了。字母包含大小寫,因此使用[a-zA-Z]。若是去掉^和$,那麼僅僅是匹配user字符串中是否包含字母,使用indexOf()或者includes()代替。

var user = 'hyy' //能夠把hyy改爲任意字符來測試。
if (/^[a-zA-Z]+$/g.test(user)) {} //if(true){}

場景3:帳號只能是字母開頭,而且字母和數字的組合,長度範圍是6-10。

單打了2輪,不夠爽,來一套組合拳。上面學習了 ^ $ [0-9] [a-zA-Z] + 這幾個正則符號的使用,必定要記下來,很經常使用的。這組合拳彷佛有點複雜,不過不怕,遇到這種問題,咱們第一步仍是提取規則:
字母開頭;
字母和數字組合;
長度6-10。

一、你腦子裏要想着 /^what❓$/.test(user) 的結構。

二、字母開頭,那麼就是第一個字符必須是字母。你須要學習一個新的正則,大括號{n,m},x{1}表示匹配前面的字符1次,x{2}表示匹配2次符合x的字符,還能夠寫成x{1,3},表示匹配符合x正則的符合最少1次,最多3次。說這段話你一會兒理解不了,就跳過。咱們只看{1}這種狀況。因此,如今加上字母開頭這條規則以後,正則變成了 /^[a-zA-Z]{1}}/,注意,我暫時沒有寫結束符號,最後再加上。

/^[a-zA-Z]{1}}/

三、字母和數字組合,咱們是否是要寫成[a-zA-Z]d呢?其實還有一個更好的辦法,你又學到了一個新的正則w,w和([a-zA-Z]|d)相同,都表示字母和數字的組合。順便再講講 () 和 | 這2個正則的含義。在正則中,()表示一個group,也就是組,|表示或,因此([a-zA-Z]|d)的含義就是字母或者數字,再使用()括起來,造成了一個正則組。以爲括號複雜的話,使用w就好了。

/^[a-zA-Z]{1}\w/

四、終於快搞定了,最後一條規則,長度6-10,若是你不想使用正則,那麼長度也能夠根據字符串的length來判斷,這樣的話,上面的正則能夠加上結束符號$直接使用了。\w後面我悄悄加了個+,由於要匹配後面的全部字母和數字至少一次,而後再寫$結束:

if(/^[a-zA-Z]{1}\w+$/g.test('Hyy123') && 'Hyy123'.length > 5 && 'Hyy123'.length < 11){}

可是既然學習正則,那就用正則的方式去解決,其實更加簡單。
利用上面學習的大括號{},咱們能夠很容易實現長度控制。直接給你看最終形態:

if(/^[a-zA-Z]{1}\w{5,9}$/g.test('Hyy123')){} //true

這個最終形態的正則能夠拆分紅幾部分來看:

^:開頭
[a-zA-Z]{1}:第一個字符匹配一次,且只能是字母
\w{5,9}:後面的字符是字母或者數字的組合,且長度是6-10,由於第一個字符佔了一個長度,因此這裏匹配的是5-9的長度
$:結束

場景4:密碼只能是6位數字。

這個就簡單多了。規則首先是數字,而後長度是6。最後的g可要可不要。

/^\d{6}$/

match()

test()一般用來驗證字符串是否符合某個規則,而match()是從字符串裏面提取符合某規則的字符。對前端來講,match使用的場景很少,可是像微信端app的對話系統的表情包,就使用到了一個特定的規則。

你在給一個朋友發微信的時候,通常是直接點擊某個表情,而後發送,可是其實還能夠輸入一些字符組合,而後發送後,在聊天界面,微信系統會自動匹配出來某個表情。這裏我猜想就是用match作的字符串處理,又或許有什麼我不知道的高深技術吧。

我用一個組合拳的例子介紹一下match的使用場景:

一、有這樣一段文字:

我是一個前端,工做1年了,如今失業,想進入騰訊工做,這是個人聯繫方式:15527578846

二、假設你來應聘前端工程師,我是面試官,我給你提這麼幾個需求,從這段話中,提取聯繫方式,工做年限,你該怎麼辦??

三、有時候前端也會碰到相似的需求,第一步是分析規則:
聯繫方式:聯繫方式可能有不少種狀況,好比手機號、微信、qq、座機號等,好吧,這樣一看的確很是複雜,那麼咱們只考慮手機號的狀況。
工做年限:工做年限是阿拉伯數字。

四、考慮用什麼方法去匹配,test仍是match?這裏一看就是用match,先分析第一個,提取聯繫方式,或者說提取手機號。手機號自己也有特定的規則:

開頭是1;
長度11;
第2位是3或5或7;
第3位到第11位是0到9的數字。

或許還有更加詳細的手機號規則,你能夠網上查一下手機號的組成規則。

五、如今開始用正則匹配出來吧,不要怕,很簡單的。看第一條,開頭是1,啥,開頭,你是否是又想到了/^1/。對不起,你這樣寫就錯了。由於字符串的開頭是 "我",因此你換一下寫法就對了。

/1/

六、長度是11位,這個很重要,但後面才匹配長度,先看第二位數字的規則,三、五、7,用正則組的寫法就是 (3|5|7)。

/1(3|5|7){1}/ //這裏再加個{1}表示匹配前面括號裏的規則1次。這樣就能匹配到字符串裏的15了。

七、第3到第11位是0-9的數字,那麼就是d{9},由於後面還有9位數字,因此匹配9次便可。

/1(3|5|7){1}\d{9}/ //匹配出來就是15527578846

八、看看完整的寫法,match匹配出來的是一個數組,

var s = '我是一個前端,工做1年了,如今失業,想進入騰訊工做,這是個人聯繫方式:15527578846'

//加g匹配完整的正則
s.match(/1(3|5|7){1}\d{9}/g) // ['15527578846']

//不加g匹配完整的正則的同時,還將()裏面的小正則也匹配出來。
s.match(/1(3|5|7){1}\d{9}/)
//["15527578846", "5", index: 35, input: "我是一個前端,工做1年了,如今失業,想進入騰訊工做,這是個人聯繫方式:15527578846"]

九、這個正則雖然提取出來了手機號,可是並不完善,更加精確的匹配須要判斷開頭和結尾不能再跟着其餘數字,好比991552757884699,這樣仍舊會把99中間的11位數字提取出來。固然,這不屬於當前場景考慮的問題了。

十、分析第二個,工做年限,工做年限有個特色,就是他是數字,而且後面必定跟着「年」,前面跟着「工做」,這樣一來規則就很簡單了。正則裏面的問號 ? 表示問號前面的規則匹配0次或者1次。意思就是若是"工做"不存在,正則也成立。好比原句子是「工做1年」,變成「1年」。一樣能夠匹配。

s.match(/(工做)?(\d{1,2})年/) //(\d{1,2})年限最少1次,最多2次,我不信你工做了100年。
// ["工做1年", "工做", "1", index: 7, input: "我是一個前端,工做1年了,如今失業,想進入騰訊工做,這是個人聯繫方式:15527578846"]
s.match(/(工做)?(\d{1,2})年/)[2] //目標結果 1

replace()

在前端開發中,這個方法很經常使用,看這麼幾個場景:

場景1:將字符串裏面的逗號替換成感嘆號

var s = '我是一個前端,上班1年了,如今失業,想進入騰訊工做,這是個人聯繫方式:15527578846'
s.replace(/,/g, "!")
// "我是一個前端!上班1年了!如今失業!想進入騰訊工做!這是個人聯繫方式:15527578846"

場景2:將手機號最後8位替換成 *

一、首先你要使用test判斷是不是手機號,而後再執行替換語句。

二、使用match提取出手機號的後8位數字。

'15527578846'.match(/^\d{3}((\d){8})$/)
//["15527578846", "27578846", "7", index: 0, input: "15527578846"]

var r = '15527578846'.match(/^\d{3}((\d){8})$/)[1] //"27578846"

三、接着執行replace匹配變量r,而後執行替換。

'15527578846'.match(/^\d{3}((\d){8})$/)
//["15527578846", "27578846", "7", index: 0, input: "15527578846"]

var r = '15527578846'.match(/^\d{3}((\d){8})$/)[1] //"27578846"
'15527578846'.replace(r, '********') // "155********"

四、咱們能夠將這個過程封裝成一個函數。

function regexTest(tel) {
    if(typeof tel !== 'string') throw Error('類型不對!');
    tel.match(/^\d{3}((\d){8})$/);
    var r = tel.match(/^\d{3}((\d){8})$/)[1];
    return tel.replace(r, '********');
}
regexTest('15527578846') // "155********"

總結

本章你所學到的是正則入門的知識。掌握這些經常使用的語法和寫一個正則的思路,對於一些簡單的正則,應該可以本身寫出來。後面還會繼續跟你們分享各類正則需求的實現思路。

下一章:正則實戰篇

正則系列文章整理到了github:https://github.com/hyy1115/Re...

相關文章
相關標籤/搜索