摘要:對前端來說,使用的場景不多,但是像微信端的對話系統(tǒng)的表情包,就使用到了一個特定的規(guī)則。我是一個前端,工作年了,現(xiàn)在失業(yè),想進入騰訊工作,這是我的聯(lián)系方式這個正則雖
我發(fā)現(xiàn)有個別字符被這個編輯器給刷掉了,但是灰色區(qū)域顯示正常,以灰色區(qū)域代碼為準
什么玩意?在我剛開始學習編程的時候,就聽過正則了,也聽說正則很牛逼,懂正則的更牛逼。但是苦于沒有人指點,也沒有使用正則的場景,自己看教程又懵逼,直到現(xiàn)在,才發(fā)現(xiàn)了入門的訣竅。
在不同的編程語言中,正則表達式的寫法會有所不同,這里我們討論的是JavaScript正則寫法。
學習正則,不要憑空想象,要使用開發(fā)工具去測試,推薦你使用在線正則測試網(wǎng)站:https://regex101.com,或者使用瀏覽器控制臺。
最簡單的正則正則在自然語言處理中廣泛運用到,對前端開發(fā)者來說,最常見的正則是表單上的一些驗證。如果你不熟悉正則,在寫表單的時候,是從網(wǎng)上直接搜索某某正則的寫法,然后copy過來。
但是,在你看完這篇文章之后,我希望你可以直接寫出一些簡單的正則,不再需要百度了。
現(xiàn)在介紹一種最簡單的正則(匹配指定的文本):
下面是一段美文,我們現(xiàn)在想把里面的某個字,比如(的),匹配出來。
var s = "前世茫茫人海的擦肩,種了今生的遇見,在花海的某一朵間,是你最美的笑顏。繁花三千,只為一人留戀,幾度春秋,只等你花開的一面。多少來來回回,夢里若隱若現(xiàn),舉著思念的酒盞,輕酌夜色微涼,讓回憶的美好舞翩翩。擱淺了時光,靜默緣分的一端,遠處的風景,依然是你微笑的眉眼。" s.match(/的/g)
我們使用到了match方法來做匹配,來分析一下這個寫法,s表示字符串,g表示全局匹配,如果去掉g,只能匹配出來第一個(的)。
是不是最簡單的正則?你需要匹配什么內(nèi)容,就直接在//之間寫這個字符,然后正則系統(tǒng)會自動從字符串去查找。
可能這樣說不是很直觀,我奉獻一張101的截圖,特別關注紅框部分,最上邊是正則的輸入框,下面是字符串,右邊是匹配出來的字符:
上面的例子中,使用到了match(),可以匹配出來字符,并且返回值是一個數(shù)組。還有一個常用的方法是test(),test的返回值是bool類型,通常用來寫在if語句中判斷一個字符串是否滿足正則表達式,在表單驗證中經(jīng)常用到。還有一個常用的方法是replace(),replace和match比較像,都能匹配出字符,但是replace還有第二個參數(shù)可以做字符替換。
下面我們會講到三個方法的具體使用場景。往下看!
正則有各種各樣的符號,一般很難背下來,但是常用的符號多練習幾遍,印象就會深刻。
我們用實際的例子來分析test()以及正則的實現(xiàn),以注冊表單為例:
test()和match()寫法剛好反過來,test是正則寫在前面,字符串寫到函數(shù)的參數(shù)中。
看到這樣一道題目,你首先要思考2個字——“規(guī)則”,賬號是主體,賬號的規(guī)則是只能是數(shù)字,那么就是說輸入非數(shù)字就不能匹配。
了解了規(guī)則之后,就很簡單了,正則提供了默認匹配數(shù)字的字符,d或者是[0-9],那么是不是直接/d/.test("123")就行了呢?當然不是,d表示是數(shù)字,你還需要加上一個特殊字符,表示匹配所有的數(shù)字,因為一個字符串有N個數(shù)字,全部都要匹配成功。
這里我使用的是+,加號表示至少匹配一次數(shù)字,比如123,如果使用d,就只能一個個匹配出來[1,2,3],這需要在match方法中使用,在test方法中,必須匹配整個字符串是否符合正則。改成d+之后,匹配的是整個字符串中的數(shù)字,是不是離我們的最終結果很接近了。
上面的操作似乎已經(jīng)可以匹配出數(shù)字了,但是記住,test()方法中,如果你要驗證整個字符串只能是數(shù)字,必須加上正則的開始符號^和結束符號$,表示的是從字符串"123"開頭匹配到結尾都必須滿足數(shù)字,如果中間插入其他字符"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:賬號只能是字母
數(shù)字匹配完了,換成字母會不會呢?只要把d或[0-9]改成字母的正則就行了。字母包含大小寫,所以使用[a-zA-Z]。如果去掉^和$,那么僅僅是匹配user字符串中是否包含字母,使用indexOf()或者includes()代替。
var user = "hyy" //可以把hyy改成任意字符來測試。 if (/^[a-zA-Z]+$/g.test(user)) {} //if(true){}場景3:賬號只能是字母開頭,并且字母和數(shù)字的組合,長度范圍是6-10。
單打了2輪,不夠爽,來一套組合拳。上面學習了 ^ $ [0-9] [a-zA-Z] + 這幾個正則符號的使用,一定要記下來,很常用的。這組合拳似乎有點復雜,不過不怕,遇到這種問題,我們第一步還是提取規(guī)則:
字母開頭;
字母和數(shù)字組合;
長度6-10。
1、你腦子里要想著 /^what?$/.test(user) 的結構。
2、字母開頭,那么就是第一個字符必須是字母。你需要學習一個新的正則,大括號{n,m},x{1}表示匹配前面的字符1次,x{2}表示匹配2次符合x的字符,還可以寫成x{1,3},表示匹配符合x正則的符合最少1次,最多3次。說這段話你一下子理解不了,就跳過。我們只看{1}這種情況。所以,現(xiàn)在加上字母開頭這條規(guī)則之后,正則變成了 /^[a-zA-Z]{1}}/,注意,我暫時沒有寫結束符號,最后再加上。
/^[a-zA-Z]{1}}/
3、字母和數(shù)字組合,我們是不是要寫成[a-zA-Z]d呢?其實還有一個更好的辦法,你又學到了一個新的正則w,w和([a-zA-Z]|d)相同,都表示字母和數(shù)字的組合。順便再講講 () 和 | 這2個正則的含義。在正則中,()表示一個group,也就是組,|表示或,所以([a-zA-Z]|d)的含義就是字母或者數(shù)字,再使用()括起來,形成了一個正則組。覺得括號復雜的話,使用w就行了。
/^[a-zA-Z]{1}w/
4、終于快搞定了,最后一條規(guī)則,長度6-10,如果你不想使用正則,那么長度也可以根據(jù)字符串的length來判斷,這樣的話,上面的正則可以加上結束符號$直接使用了。w后面我悄悄加了個+,因為要匹配后面的所有字母和數(shù)字至少一次,然后再寫$結束:
if(/^[a-zA-Z]{1}w+$/g.test("Hyy123") && "Hyy123".length > 5 && "Hyy123".length < 11){}
但是既然學習正則,那就用正則的方式去解決,其實更加簡單。
利用上面學習的大括號{},我們可以很容易實現(xiàn)長度控制。直接給你看最終形態(tài):
if(/^[a-zA-Z]{1}w{5,9}$/g.test("Hyy123")){} //true
這個最終形態(tài)的正則可以拆分成幾部分來看:
^:開頭 [a-zA-Z]{1}:第一個字符匹配一次,且只能是字母 w{5,9}:后面的字符是字母或者數(shù)字的組合,且長度是6-10,因為第一個字符占了一個長度,所以這里匹配的是5-9的長度 $:結束場景4:密碼只能是6位數(shù)字。
這個就簡單多了。規(guī)則首先是數(shù)字,然后長度是6。最后的g可要可不要。
/^d{6}$/match()
test()通常用來驗證字符串是否符合某個規(guī)則,而match()是從字符串里面提取符合某規(guī)則的字符。對前端來說,match使用的場景不多,但是像微信端app的對話系統(tǒng)的表情包,就使用到了一個特定的規(guī)則。
你在給一個朋友發(fā)微信的時候,一般是直接點擊某個表情,然后發(fā)送,但是其實還可以輸入一些字符組合,然后發(fā)送后,在聊天界面,微信系統(tǒng)會自動匹配出來某個表情。這里我猜測就是用match做的字符串處理,又或許有什么我不知道的高深技術吧。
我用一個組合拳的例子介紹一下match的使用場景:
1、有這樣一段文字:
我是一個前端,工作1年了,現(xiàn)在失業(yè),想進入騰訊工作,這是我的聯(lián)系方式:15527578846
2、假設你來應聘前端工程師,我是面試官,我給你提這么幾個需求,從這段話中,提取聯(lián)系方式,工作年限,你該怎么辦??
3、有時候前端也會碰到類似的需求,第一步是分析規(guī)則:
聯(lián)系方式:聯(lián)系方式可能有很多種情況,比如手機號、微信、qq、座機號等,好吧,這樣一看的確非常復雜,那么我們只考慮手機號的情況。
工作年限:工作年限是阿拉伯數(shù)字。
4、考慮用什么方法去匹配,test還是match?這里一看就是用match,先分析第一個,提取聯(lián)系方式,或者說提取手機號。手機號本身也有特定的規(guī)則:
開頭是1; 長度11; 第2位是3或5或7; 第3位到第11位是0到9的數(shù)字。
或許還有更加詳細的手機號規(guī)則,你可以網(wǎng)上查一下手機號的組成規(guī)則。
5、現(xiàn)在開始用正則匹配出來吧,不要怕,很簡單的。看第一條,開頭是1,啥,開頭,你是不是又想到了/^1/。對不起,你這樣寫就錯了。因為字符串的開頭是 "我",所以你換一下寫法就對了。
/1/
6、長度是11位,這個很重要,但后面才匹配長度,先看第二位數(shù)字的規(guī)則,3、5、7,用正則組的寫法就是 (3|5|7)。
/1(3|5|7){1}/ //這里再加個{1}表示匹配前面括號里的規(guī)則1次。這樣就能匹配到字符串里的15了。
7、第3到第11位是0-9的數(shù)字,那么就是d{9},因為后面還有9位數(shù)字,所以匹配9次即可。
/1(3|5|7){1}d{9}/ //匹配出來就是15527578846
8、看看完整的寫法,match匹配出來的是一個數(shù)組,
var s = "我是一個前端,工作1年了,現(xiàn)在失業(yè),想進入騰訊工作,這是我的聯(lián)系方式: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年了,現(xiàn)在失業(yè),想進入騰訊工作,這是我的聯(lián)系方式:15527578846"]
9、這個正則雖然提取出來了手機號,但是并不完善,更加精確的匹配需要判斷開頭和結尾不能再跟著其他數(shù)字,比如991552757884699,這樣仍舊會把99中間的11位數(shù)字提取出來。當然,這不屬于當前場景考慮的問題了。
10、分析第二個,工作年限,工作年限有個特點,就是他是數(shù)字,并且后面一定跟著“年”,前面跟著“工作”,這樣一來規(guī)則就很簡單了。正則里面的問號 ? 表示問號前面的規(guī)則匹配0次或者1次。意思就是如果"工作"不存在,正則也成立。比如原句子是“工作1年”,變成“1年”。同樣可以匹配。
s.match(/(工作)?(d{1,2})年/) //(d{1,2})年限最少1次,最多2次,我不信你工作了100年。 // ["工作1年", "工作", "1", index: 7, input: "我是一個前端,工作1年了,現(xiàn)在失業(yè),想進入騰訊工作,這是我的聯(lián)系方式:15527578846"] s.match(/(工作)?(d{1,2})年/)[2] //目標結果 1replace()
在前端開發(fā)中,這個方法很常用,看這么幾個場景:
場景1:將字符串里面的逗號替換成感嘆號var s = "我是一個前端,上班1年了,現(xiàn)在失業(yè),想進入騰訊工作,這是我的聯(lián)系方式:15527578846" s.replace(/,/g, "!") // "我是一個前端!上班1年了!現(xiàn)在失業(yè)!想進入騰訊工作!這是我的聯(lián)系方式:15527578846"場景2:將手機號最后8位替換成 *
1、首先你要使用test判斷是否是手機號,然后再執(zhí)行替換語句。
2、使用match提取出手機號的后8位數(shù)字。
"15527578846".match(/^d{3}((d){8})$/) //["15527578846", "27578846", "7", index: 0, input: "15527578846"] var r = "15527578846".match(/^d{3}((d){8})$/)[1] //"27578846"
3、接著執(zhí)行replace匹配變量r,然后執(zhí)行替換。
"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********"
4、我們可以將這個過程封裝成一個函數(shù)。
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********"總結
本章你所學到的是正則入門的知識。掌握這些常用的語法和寫一個正則的思路,對于一些簡單的正則,應該能夠自己寫出來。后面還會繼續(xù)跟大家分享各種正則需求的實現(xiàn)思路。
下一章:正則實戰(zhàn)篇
正則系列文章整理到了github:https://github.com/hyy1115/Re...
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/91825.html
摘要:正則正則匹配的是零寬斷言這一塊我還沒有完成掌握,它的大概意思是,獲取某個字符或者某些字符前面的正則或者后面的正則。下一章正則表達式理論鞏固篇正則系列文章整理到了 如果你正則基礎為0,請先看第一篇文章:JavaScript正則表達式入門心得 實戰(zhàn)篇 上一章我分享了正則入門的一些體會以及注意事項。這一章開始挑一些常用的比較復雜一點的需求來練習一下。 場景1:驗證email是否合法 郵箱種類...
閱讀 1635·2021-10-14 09:43
閱讀 5564·2021-09-07 10:21
閱讀 1289·2019-08-30 15:56
閱讀 2133·2019-08-30 15:53
閱讀 1243·2019-08-30 15:44
閱讀 2020·2019-08-30 15:44
閱讀 1331·2019-08-29 17:24
閱讀 761·2019-08-29 15:19