with (javascript)
前一篇淺入正則(一)瞭解了實例化一個RegExp對象、RegExp的原型方法、RegExp的對象屬性這些基礎,大體知道正則怎麼用,這一篇主要想了解一下正則怎麼寫。javascript
元字符表隨便就查獲得,但這是會寫正則最重要的基礎,這裏簡單分紅兩類並按個人理解簡單註釋。java
運算符 & 限定符正則表達式
{ "\": "除語義類元字符中的使用,\ 爲轉義字符,好比想要匹配一個'(',直接使用'('會被認做分組的開始,須要使用\轉義, '/\(/'", "^": { "開頭": "在非'[]'中使用,表示匹配開頭的意思,若是RegExp對象設置多行(m)屬性,也會匹配換行符\n及\r以後的位置", "非": "在'[]'中,表示取反,例如:'/[^a]/',表示匹配不是a的字符" }, "$": "匹配結束的位置,若是RegExp對象設置多行(m)屬性,也會匹配換行符\n及\r以前的位置", "*": "任意的意思,表示匹配前面緊接着的子表達式0次或屢次", "+": "表示匹配前面緊接着的子表達式1次或屢次,也就是最少1次", "?": { 1: "表示匹配前面緊接着的子表達式0次或1次,也就是最多1次", 2: "非貪婪模式:前提是緊跟在其餘限定符後面,好比'*'、'+'、'{n,m}'等,表示儘量少的匹配,好比'{n,m}',例如: '/\d{4,6}?/g',假如使用這個正則test一段字符串'123456abc',則會盡量少的匹配,也就是每次test只匹配4個,而後lastIndex被置爲4,默認狀況下爲貪婪模式,每次會匹配6個,lastIndex會重置爲6,若是沒法匹配6個纔會嘗試匹配5個,4個" }, "{n}": "表示匹配前面緊接着的子表達式n次,n爲非負整數", "{n,}": "表示匹配前面緊接着的子表達式n次或更屢次,也就是最少n次,n爲非負整數", "{n,m}": "表示匹配前面緊接着的子表達式n次到m次,也就是最少匹配n次,最多匹配m次,n <= m 且n和m均爲非負整數", ".": "除'\n'外的任意字符", "|": "或,例如'/a|bcd/'能夠匹配'a'或者'bcd','/(a|b)cd/'能夠匹配'acd'或者'bcd'", "-": "僅當在'[]'中能夠表示鏈接符,'/[a-z]/'、'/A-Z/'、'/0-9/'分別表示a到z、A到Z、0到9,其餘時間就表示中劃線", "[]": "字符集合,表示中括號中的任意字符,好比'/[acb123ABC]/'表示匹配到'acb123ABC'中任意一個就能夠", "()": "分組,和咱們日常的加減運算中的()差很少,能夠理解爲肯定優先級的意思,不過js正則中的()分組能夠經過'$1 - $9'獲取匹配結果中,每個分組對應的匹配值,也就是'$1'也就是第一個分組的子表達式匹配成功的結果,例如:'abc123ef'.replace(/(\w)(\d){3}/g,'$2$1'),例子中,匹配(一個字母)緊接着(一個數字)循環了三次,'$1'就是後面緊接着數字的一個字母,也就是'c','$2'就是一個數字,也就是'(\d)'的最後一個匹配結果'3',由於數字循環了三次,因此三個數字會被替換成'$1',而c會被替換成'$2',結果就是'ab3cef'", "(?:)": "和()差很少一個意思,只是()中的分組內容不會被存儲到'$1 - $9'的集合中", "(?=)": "正向前瞻,也就是前面的表達式緊接着的表達式,要符合(?=)的=後面跟着的表達式,例如:'/[a-z](?=\d)/',只會匹配後面緊接着數字的小寫字母,可是數字並不會出如今匹配結果中且不會被存儲到'$1 - $9'的集合中", "(?!)": "負向前瞻,也就是前面的表達式緊接着的表達式,要符合(?!)的 != 後面跟着的表達式,例如:'/[a-z](?!\d)/',只會匹配後面緊接着不是數字的小寫字母,可是數字並不會出如今匹配結果中且不會被存儲到'$1 - $9'的集合中" }
基礎的運算符和限定符無非就這幾個,說到運算符就有優先級,上面的運算符的優先級爲:segmentfault
{ "一級": "'\'", "二級": "'()'、'(?:)'、'(?=)'、'[]'", "三級": "'*'、"+"、'?'、'{n}'、'{n,}'、'{n,m}'", "四級": "'^'、'$'、'其餘元字符及字符'", "五級": "'|'", }
語義類元字符數組
{ "\b": "單詞邊界,也就是前面或者後面要跟着個空格", "\B": "非單詞邊界,也就是必須在單詞中間,先後不能有空格", "\d": "匹配一個數字字符,等價於'[0-9]'", "\D": "匹配一個非數字字符,等價於'[^0-9]'", "\w": "匹配任意單詞字符和下劃線'_',等價於'[a-zA-Z0-9_]'", "\W": "匹配任意非單詞字符及非下劃線,等價於'[^a-zA-Z0-9_]'", "\s": "匹配任意空白字符,含空格、製表符、換頁符等", "\S": "匹配非空白字符", //···還有不少不經常使用的,用時再查吧 }
前一篇筆記只解析了RegExp對象的原型方法,可是對於正則表達式,一些字符串的方法一樣可使用在正則上。code
replace也屬於常用的一個方法,在具體到和正則表達式一塊兒使用時是:stringObject.replace(RegExpObject,string|function)
,上例子:regexp
var str1 = "2017-07-12"; var reg1 = /(\d{4})-(\d{2})-(\d{2})/g; str1.replace(reg1, function(a,b,c,d,e){ // a/b/c/d/e分別表明: 匹配結果/第一個分組匹配值/第二個分組匹配值/第三個分組匹配值/匹配成功的第一個字符的index值 console.log(a,b,c,d); //2017-07-12 2017 07 12,0 return c + "/" + d + "/" + b; }) console.log(str1); //07/12/2017
須要注意的是,string是沒有replaceAll的方法的,須要全局替換請在正在中設置全局屬性g
;對象
math方法也是string的方法,match方法用法和exec很類似,一樣返回數組。ip
非全局正則調用,輸出結果和exec類似,無匹配結果則返回null,有則返回數組,分別存放每個子表達式匹配的結果,同時具備index和input兩個屬性:字符串
var reg1 = /([a-zA-Z]\d)+([\u4e00-\u9fa5])+/; //匹配 (大小寫字母連着一個數字) 至少一次 (再連着漢字) 至少一次 var str1 = "a11B2老cd3李e45好"; var result = str1.match(reg1); console.log(result); //["B2老", "B2", "老"]
這個結果和exec的結果徹底同樣;
全局正則調用,數組只存放全部匹配的整個正則的子字符串,而不存放正則子表達式匹配的子字符串,也沒有index和input的屬性:
var reg2 = /([a-zA-Z]\d)+([\u4e00-\u9fa5])+/g; //匹配 (大小寫字母連着一個數字) 至少一次 (再連着漢字) 至少一次 var str2 = "a11B2老cd3李e45好"; var result1 = str2.match(reg2); var result2 = str2.match(reg2); var result3 = str2.match(reg2); console.log(result1,result2,result3); //["B2老", "d3李"] ["B2老", "d3李"] ["B2老", "d3李"] console.log(result1.index,result2.input,result3); //undefined undefined ["B2老", "d3李"] 執行屢次均只輸出每個匹配完整正則的子字符串,同時也沒有index和input的屬性。
search方法返回的就是正則第一次匹配成功的開始位置,用法是stringObject.search(regexp);
同時serch方法只須要匹配成功一次,不會重置laseIndex屬性,每次都從字符串起始位置開始搜索,也會忽略全局搜索g
:
var reg3 = /([a-zA-Z]\d)+([\u4e00-\u9fa5])+/g; var reg4 = /([a-zA-Z]\d)+([\u4e00-\u9fa5])+/g; var str3 = "a11B2老cd3李e45好"; str3.search(reg3); //3 str3.search(reg3); //3 str3.search(reg4); //3 str3.search(reg4); //3 屢次搜索和是否全局均不會影響搜索結果
無論多麼複雜的正則,都是用本節中的元字符寫出來的,而在複雜的正則,用法無非也就上節和這一節中所記錄的方法。關鍵在於經常使用才能熟練,深刻才能理解。這兩節筆記只是淺入,在實踐中摸索實踐才能真的深刻淺出,一塊兒加油。