最近發(fā)現(xiàn)很多人對正則表達(dá)式一知半解,希望能通過這個(gè)教程能給你帶來一些幫助。
1.正則表達(dá)式用來做什么
現(xiàn)在有一個(gè)場景,產(chǎn)品給張三提了一個(gè)需求:
產(chǎn)品:我需要一個(gè)輸入框,這個(gè)輸入框用來輸入用戶的昵稱,昵稱的最多可以輸入6個(gè)漢字
張三:這簡單 <input maxlength=6/>
產(chǎn)品:不可以輸入空格等特殊字符
張三:String.prototype.replaceAll(' ','')
產(chǎn)品:不可以輸入不文明用語
張三:String.prototype.indexOf('fuck')!==-1
產(chǎn)品:可以輸入英文,最長12個(gè)字符
張三:你為什么不直接說最大12個(gè)字節(jié)!?。∵@個(gè)需求做不……
張三憤怒轉(zhuǎn)身看到產(chǎn)品突然手里一個(gè)方方正正又有點(diǎn)長的固態(tài)物體,咽了咽口水,說這個(gè)需求做不好我就不下班!?。?/p>
旁邊的小明聽了,笑著說:張三你又要加班啊
張三吞吞吐吐:程序員的事怎么能叫加班呢
接下來便是一些聽不懂的話,什么晨興寫代碼,帶月荷機(jī)歸,辦公室頓時(shí)充滿了歡快的氣氛。
聰明的你現(xiàn)在一定想到了這不正是正則表達(dá)式的用武之地嗎。沒錯(cuò) 正則表達(dá)式就是設(shè)置一個(gè)字符串的規(guī)則,他可以判斷字符串是否符合正則表達(dá)式的規(guī)則,也可以匹配字符串中符合規(guī)則的部分子串。
正則表達(dá)式十分強(qiáng)大,但使用的同時(shí)我們需要知道他的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):
1.可以用少量的代碼來匹配復(fù)雜的內(nèi)容
2.大多情況下正則表達(dá)式的時(shí)間復(fù)雜度為o(n)
缺點(diǎn):
- 較差可讀性帶來較大的修改難度
- 一旦產(chǎn)生回溯性能較差
2. 正則表達(dá)式長什么樣?
正則表達(dá)式由兩個(gè)斜杠和斜杠之間的規(guī)則以及第二個(gè)斜杠之后的屬性描述符組成,例如:
/a{2,3}/g
這個(gè)正則表達(dá)式就會匹配字符串中連續(xù)出現(xiàn)的a字符2次到3次部分。
正則表達(dá)式中用一些特殊的字符來表示某些字符的集合,這里我們介紹一些常用的:
(1) []中括號用來表示一個(gè)匹配的字符集中的匹配字符,在中括號中出現(xiàn)的內(nèi)容都是||或關(guān)系。如:/[abc]/他可以匹配字符串中的a或b或c。他還有以下用法:
/[A-z]/ 指定一個(gè)字母范圍進(jìn)行匹配。他將匹配從大寫的A到小寫的z等52個(gè)英文字母也可以/[A-E]/匹配A、B、C、D、E五個(gè)字母。
/[0-9]/指定一個(gè)數(shù)字范圍進(jìn)行匹配。他將匹配從0到9的10個(gè)字符,也可以用\d來代表[0-9]匹配數(shù)字。如:/\d/{3}用來配位3位數(shù)字。
/[\u4e00-\u9fa5]/指定一個(gè)Unicode字符集范圍進(jìn)行匹配。他將匹配從字符集中從\u4e00到\u9fa5等字符。
/[^a-f]/指定一個(gè)字母范圍,匹配不是這個(gè)字母范圍的內(nèi)容,這里的^是取反操作,表示匹配非a到f的字母。
(2) {} 花括號用來表示連續(xù)匹配次數(shù),如:/[abc]{3,5}/ 他可以匹配abc中任意字符連續(xù)出現(xiàn)3到5次,如abc、acc、aaaaa都符合abc中任意字符連續(xù)出現(xiàn)3到5次。
除了上面的例子他有如下幾種寫法:
/[abc]{3}/ 表示固定連續(xù)匹配 a-c三次
/[abc]{3,}/表示至少連續(xù)匹配3次
/[abc]*/ *表示匹配0次或多次,等同于/[abc]{0,}/
/[abc]?/ 表示匹配0次或1次,等同于/[abc]{0,1}/
/[abc]+/ 表示匹配1次或多次,等同于/[abc]{1,}/
*、?、+雖然沒用花括號,但作用是一樣的
(3) ()小括號被稱為捕獲括號,他會匹配括號中的規(guī)則并記錄,用來獲取字符串中的符合規(guī)則的子串
(4)^ 匹配以正則表達(dá)式規(guī)則開頭的字符串。如:/^a/匹配以a開頭的字符串 abc,在[]中出現(xiàn)則表示取反操作,如/[^a]/則表示匹配不是a的字母,千萬不要和在[]外的^搞混。
(5)$匹配以正則表達(dá)式規(guī)則結(jié)尾的字符串。如:/js\$/匹配以js結(jié)尾的字符串如index.js。配合^使用,/^abc$/匹配以a開頭,中間為b,以c結(jié)尾的字符串。
(6)屬性描述符
屬性描述符寫在第二個(gè)斜線之后/a/g,他用來描述正則表達(dá)式的匹配模式常用的有:
g 表示全局匹配,例如/a/g將匹配字符串中所有的a
i 表示忽略大小寫,例如/a/i 也可以匹配大寫的A如:aAA
也可以連續(xù)使用幾個(gè)描述符如/^a{3}$/gi他與aAa是匹配的
3.先行斷言、后行斷言、正向否定查找、反向否定查找
(1)先行斷言
/a(?=b)/ 這是一個(gè)簡單的先行斷言,當(dāng)a后面的值為b時(shí),匹配a。如abc,則匹配a,acc則不匹配a。
小明讓張三去買個(gè)西瓜,囑咐他,如果西瓜上畫著喜羊羊,那就買。如果沒畫著喜羊羊就不買,因?yàn)樾∶飨矚g畫著喜羊羊的西瓜。這就是一個(gè)先行斷言,首先要找到西瓜,然后西瓜上必須畫著喜羊羊。
我們的目的是西瓜,西瓜是我們最終想要的結(jié)果,而畫著喜羊羊是用來描述西瓜的其他特征,是西瓜的描述。匹配到的結(jié)果是畫著喜羊羊的西瓜。
如上面的例子,/a(?=b)/g ,abacc字符串匹配到的結(jié)果只有b前面的a,而c前面的a是不會匹配到的,而不是ab。
(2)后行斷言
/(?<=a)b/g 這是一個(gè)簡單的后行斷言,當(dāng)b的前面的值為a時(shí),匹配b。abccb字符串匹配到的結(jié)果是a后邊的b,不會匹配c后邊的b。
(3)正向否定查找
/a(?!b)/這是一個(gè)簡單的正向否定查找,當(dāng)a的后面的值不是b時(shí),匹配a
(4)反向否定查找
/(?<!a)/b 這是一個(gè)簡單的反向否定查找,當(dāng)b前面的值不是a是,匹配b
注意:先行斷言、后行斷言、正向否定查找和反向否定查找都是匹配項(xiàng)的描述,是一個(gè)形容詞,不是有效的匹配項(xiàng)。
這個(gè)描述有時(shí)是一個(gè)很寬泛的匹配性如/a(?=[b-z])/,則a后面跟著b到z 的任意字符都是可以的,但是如果跟著一個(gè)數(shù)字就不可以。
例如:先行斷言之后又跟著一個(gè)數(shù)字的匹配項(xiàng),如:/a(?=[b-z])[0-9]/那么這個(gè)正則就是無效的,無論什么字符串都將返回false,因?yàn)楸仨毱ヅ?code>a后邊跟著b到z的字符串,a后邊又必須是[0-9],這互相沖突了。將他們拆解成兩個(gè)正則或許更清晰一些:字符串必須同時(shí)滿足/a(?=[b-z])/和/a[0-9]/,根本不存在這樣的字符串。
還有就是使用先行斷言時(shí)需要注意/^a(?<=\.js)$/,這樣是匹配不到任何結(jié)果的,因?yàn)檫@樣是必須匹配以a結(jié)尾,而且a后邊還得跟著.js,這樣是互相沖突的,正確的寫法應(yīng)該是/^a\.js$/
(完)