理解javascript正則表達式
了解RegExp類型:
ECMAScript通過RegExp類型來支持正則表達式。 var expression=/pattern/flags;
正則表達式的模式(pattern)部分:
可以是任何簡單或復(fù)雜的正則表達式,可以包含字符類,限定符,分組,向前查找,反向引用。 關(guān)于正則表達式中各種特殊字符(如 \,^,$,\w,\b 等)的含義可以參考 MDN 正則表達式-特殊字符 的整理。這里我們簡單介紹一下向前查找和反向引用。
向前查找:正則表達式向前使用一些字符而不移動這些字符的位置,分為正向前預(yù)搜索也叫正向肯定查找( x(?=y) )與負(fù)向前預(yù)搜索也叫正向否定查找( x(?!y) )。
反向引用:標(biāo)識字符串中可以提供的重復(fù)字符或字符串,可以使用捕獲組反向引用匹配。帶編號的反向引用 \number number是正則表達式中捕獲組的序號位置。
1、表達式 \1~\9 解釋為反向引用而不是八進制代碼。 /\b(\w+)\s\1/.exec('s_ s_');//["s_ s_", "s_"]
2、如果多位表達式的第一個數(shù)字是8或者9(如 \80 或 \91 ),則該表達式將被解釋為文本。 /\b(\w+)\s\80/.exec('s_ 800');//["s_ 80", "s_"]
3、對于編號為 \10 或更大值的表達式,如果存在與該編號對應(yīng)的反向引用,則將該表達式視為反向引用。否則將這些表達式解釋為八進制。
/(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)xx\10/.exec('12345678910xx10');//["12345678910xx10", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"] /(1)(2)(3)(4)(5)(6)(7)(8)(9)(10)xx\11/.exec('12345678910xx10');//null
4、如果捕獲組嵌套捕獲組,捕獲組確定的順序是內(nèi)部從外到內(nèi),外部從左到右。來個代碼體會一下。
/\b(\w+x(x))\s(\1)/.exec('s_xx s_xxSTOP');//["s_xx s_xx", "s_xx", "x", "s_xx"]
5、如果正則表達式包含對未定義的組成員的反向引用,則會發(fā)生分析錯誤,根據(jù)語言的不同正則表達式引擎將引發(fā) ArgumentEXception 。對于javascript會返回null。/\b(\w+)\s\2/.exec('s_ 8');//null
反向引用實例代碼:捕獲組捕獲到的內(nèi)容不僅可以在正則表達式外部通過程序進行引用( RegExp.$n )也可以在正則表達式內(nèi)部進行引用( \number ,這種引用方式就是反向引用)。
//表達連續(xù)三個相同的小寫,{2}應(yīng)用在\1身上 /([a-z])\1{2}/.exec('aaa');//["aaa", "a"] 復(fù)制代碼 //一道有意思的正則問題 /(\w)((?=\1\1\1)(\1))/.exec('aa bbbb');//["bb", "b", "b", "b"] /*這里捕獲組有三個,$1為(\w)中的內(nèi)容,$2為((?=\1\1\1)(\1))中的內(nèi)容: 需注意(?=\1\1\1)并不是捕獲組而是正則表達式的判斷條件,x(?=y)表示匹配x僅僅當(dāng)后面跟著y,判斷條件并不是匹配結(jié)果的一部分。所以現(xiàn)在$2的內(nèi)容為(\1)即‘b'。$3就是\1的內(nèi)容。返回的匹配項 “bb”中的第一個'b'為"aa bbbb"中的第一個'b',第二個'b'為"aa bbbb"中的第二個'b'。*/ /(\w)(x(?=\1\1\1)(\1))/.exec('aa bxbbbcb');//["bxb", "b", "xb", "b"] //這里$2的內(nèi)容為(x(?=\1\1\1)(\1))中的內(nèi)容即x(\1); //其實上面兩種模式可以簡化成/(\w)(?=\1\1\1)(\1)/表示匹配\w僅當(dāng)該\w后后面跟著三個\1,然后獲取的匹配項為該\w且其后再緊跟著\1的字符串。同理/(\w)x(?=\1\1\1)(\1)/ 復(fù)制代碼 /(\w)((?=\1\1\1)(\2))/.exec('aa bbbbv');//["b", "b", "", ""] /*捕獲組$2為((?=\1\1\1)(\2))中的內(nèi)容,由于此時還未執(zhí)行完捕獲組$2處的匹配,所以\2表示""。$3即為\2的內(nèi)容還是""。所以這條匹配被解釋為返回\w且其后緊跟3個該\w的字符串,返回\w+''就只返回'b'了。*/
正則表達式的標(biāo)志位(flags)部分:
可以帶有一個或多個標(biāo)志,用以表明正則表達式的行為。
1、g:表示全局模式,模式將被應(yīng)用于所有字符串,而非在發(fā)現(xiàn)第一個匹配項時立即停止。 'cat mat bat'.replace(/.(?=at)/g,'A');//"Aat Aat Aat"
2、i:不區(qū)分大小寫模式,在確定匹配項時忽略模式與字符串的大小寫。 'cAt mat bAt'.replace(/a/gi,'B');//"cBt mBt bBt"
3、m:多行模式,在到達一行文本末尾時還會繼續(xù)查找下一行中是否存在與模式匹配的項。
var str='cat\nmat\nbat'; str.replace(/at/gm,'AB'); /*"cAB mAB bAB"*/
正則表達式中的元字符部分:
在模式中使用這些元字符時必須轉(zhuǎn)義,如果想要匹配的字符串中包含這些字符,就需要對他們進行轉(zhuǎn)義。
( [ { \ ^ $ | ) ? * + . ] } //匹配"[bc]at" /\[bc\]at/.exec("xx[bc]at");//["[bc]at"] //匹配".at" /\.at/.exec("xx.at");//[".at"]
創(chuàng)建正則表達式:
字面量形式:形如 var expression=/pattern/flags;
RegExp構(gòu)造函數(shù):兩個參數(shù)(要匹配的字符串模式,可選的標(biāo)志字符串),不能把正則表達式字面量傳遞給構(gòu)造函數(shù),雖然即使這樣寫了也不會報錯??梢允褂米置媪慷x的任何表達式都可以使用構(gòu)造函數(shù)來定義。如下:
var p=/[bc]at/; new RegExp('[bc]at');// /[bc]at/
1、當(dāng)不傳任何參數(shù)或參數(shù)一為空字符串時, new RegExp();// /(?:)/ 或 new RegExp('');// /(?:)/ ,表示匹配 "" 但不記住匹配項( "" 其實就是 ":" 之后的空串,不記住x匹配項的規(guī)則為(?:x)),所以在匹配任何字符串時都返回 [""] 。所以由此可以猜想一下javascript正則引擎內(nèi)部機制應(yīng)該是默認(rèn)匹配 "" 且不記住該匹配項,除非顯式聲明在 ":" 之后的需要匹配的字符串,加上 "(?:)" 顯式聲明不記住匹配項。
2、由于構(gòu)造函數(shù)模式參數(shù)是字符串,所以某些情況下(是指那些已經(jīng)轉(zhuǎn)義過的字符)對字符進行雙重轉(zhuǎn)義(即在字面量形式的單重轉(zhuǎn)義再來一層轉(zhuǎn)義)。某些情況下當(dāng)然也可以進行單重轉(zhuǎn)移( new RegExp('\w');// /w/ )。注意'\'比較特殊,在字符串中也需要進行轉(zhuǎn)義。
var p=/\\n/;//轉(zhuǎn)義\,字符"\"在字符串中常需要被轉(zhuǎn)義為"\\" p.exec("\\nxx");//["\n"] var p=new RegExp("\\\\n");// /\\n/ 如果想獲得正則表達式字面量為/\\n/,需要在正則表達式中再來一層轉(zhuǎn)義 p.exec('\\nxx');//["\n"] 注意被匹配的字符串'\nxx'中\(zhòng)n的\也被轉(zhuǎn)義了 new RegExp('\\n').exec("\n");// [" "] /*RegExp('\\n')返回/\n/,即意思匹配換行符*/ new RegExp('\n').exec("\n");// [" "] /*new RegExp('\n')返回 / / ,表示并沒有進行轉(zhuǎn)義,而是返回字面量 / /,意思匹配換行符 */
3、下面給出一些單重,雙重轉(zhuǎn)義模式的參考:第幾次轉(zhuǎn)義在表中已標(biāo)出,單代表第一次轉(zhuǎn)義,雙代表在已經(jīng)有的轉(zhuǎn)義的基礎(chǔ)上再進行的轉(zhuǎn)義。
RegExp的實例屬性:
通過實例的屬性可以獲取有關(guān)模式的各種信息
global :布爾值,表示是否設(shè)置了g標(biāo)志。
ignoreCase :布爾值,表示是否設(shè)置了i標(biāo)志。
multiline :布爾值,表示是否設(shè)置了m標(biāo)志。
lastIndex :整數(shù),表示開始搜索下一個匹配項的字符位置,從0算起。前提是設(shè)置g標(biāo)志時才會有用。
source :正則表達式的字符串標(biāo)志,按照字面量形式而非構(gòu)造函數(shù)中的字符串模式返回字符串。
new RegExp('\\\\w');// /\\w/ 返回自面量形式正則表達式 new RegExp('\\\\w').source;// "\\w" 字符串
RegExp的實例方法:
exec():該方法是專門為捕獲組而設(shè)計的,參數(shù)為要匹配的字符串,返回包含第一個匹配項信息和可能有的捕獲組的數(shù)組,若未匹配到返回 null 。(返回的雖然是 Array 的實例,但還包含兩個額外的屬性: index 表示匹配項在字符串中的位置, input 表示應(yīng)用正則表達式的字符串)
var arr=new RegExp('\\\\(w)').exec('\\w');// ["\w", "w"] arr;// ["\w", "w"] arr.index;//0 arr.input;// "\w" 即exec()里的內(nèi)容
exec() 和 match() 方法的區(qū)別:
1、對于 exec() 而言,即使在模式中設(shè)置了全局標(biāo)志g,它每次也只返回一個匹配項;字符串的 match() 方法在設(shè)置g的時候可以返回全部匹配項而沒有捕獲組且返回的數(shù)組沒有index和input屬性。
2、對于exec()而言可以返回捕獲組,但match()在沒有全局g標(biāo)志時才能返回捕獲組,此時match()返回的數(shù)組有index和input屬性。
//返回全局匹配項演示比較 var arr='ababcdab'.match(/ab/g);// ["ab", "ab", "ab"] arr.index; // undefined arr.input; // undefined /ab/g.exec('ababcdab');// ["ab"] //捕獲組演示比較,match()方法和有無設(shè)置全局g標(biāo)志有關(guān) 'ababcdab'.match(/a(b)/g);// ["ab", "ab", "ab"] var arr='ababcdab'.match(/a(b)/);// ["ab", "b"] arr.index;// 0 arr.input;// 'ababcdab' /a(b)/g.exec('ababcdab');// ["ab", "b"]
3、所以在選擇使用方法的時候要先考慮好側(cè)重該方法的哪方面功能,在不設(shè)置全局標(biāo)志g的情況下,在同一個字符串上多次調(diào)用exec()則總是返回第一個匹配項的信息,而在設(shè)置全局標(biāo)志的情況下,每次調(diào)用exec()則都會在字符串中沿著上次查找的位置往后繼續(xù)查找新的匹配項。
//未設(shè)全局,每次從頭開始查找 var p=/a/; var str='ababa'; var a=p.exec(str);// ["a"]; var b=p.exec(str);// ["a"]; a==b;// false a.index==b.index;// true //設(shè)置全局,沿著上次位置繼續(xù)查找新匹配 var p=/a/g; var str='ababa'; var a=p.exec(str);// ["a"] a.index;// 0 var b=p.exec(str);// ["a"] b.index;// 2
test():接收字符串參數(shù),在模式與字符串參數(shù)匹配情況下返回 true ,否則返回 false 。常被用在 if() 中當(dāng)判斷條件。
var text="000-000-000"; var p=/((\d{3})-)\1*\2/; if(p.test(text)){ console.log('匹配成功'); }
RegExp 實例繼承 Object 的 toLocaleString() 和 toString() 方法都會返回正則表達式的字面量形式的字符串,與如何創(chuàng)建正則表達式的方式無關(guān)。 valueOf() 則返回正則表達式字面量本身。
var p=/\[new\]bi/; p.toLocaleString();// "/\[new\]bi/" p.toString();// "/\[new\]bi/" p.valueOf();// /\[new\]bi/ var p=new RegExp('\\[new\\]bi'); p.toLocaleString();// "/\[new\]bi/" p.toString();// "/\[new\]bi/" p.valueOf();// /\[new\]bi/
RegExp的構(gòu)造函數(shù)屬性:
構(gòu)造函數(shù)本身包含一些屬性(靜態(tài)屬性),這些屬性適用于作用域中的所有表達式,并且基于所執(zhí)行的最近一次正則表達式操作而變化。有長屬性名(如下代碼)和短屬性名(即$前綴形式,由于這些符號大多不是有效的ECMAScript標(biāo)識符,所以不能直接在 RegExp 構(gòu)造函數(shù)上以 "." 的方式訪問,而要通過方括號語法來訪問)兩種方式訪問這些屬性
/(.)hort/g.exec('this is a short day');// ["short", "s"] //最近一次要匹配的字符串 RegExp.input;// "this is a short day" 或RegExp["$_"]訪問; //最近一次的匹配項 RegExp.lastMatch;// "short" 或RegExp["$&"]訪問; //在最近一次要匹配的字符串中的最近一次匹配項之前的文本 RegExp.leftContext;// "this is a " 或RegExp["$`"]訪問; //在最近一次要匹配的字符串中的最近一次匹配項之后的文本 RegExp.rightContext;// " day" 或RegExp["$'"]訪問; //最近一次(最后一次)匹配的捕獲組 RegExp.lastParen;// "s" 或RegExp["$+"]訪問;
捕獲組訪問屬性:還有9個用于存儲捕獲組的構(gòu)造函數(shù)屬性,訪問語法是 RegExp.$n ,其中n取值1~9,用于獲取第n個匹配的捕獲組。在調(diào)用 exec() , test() 或 match() 等正則系列方法時這些屬性會被自動填充。
var text="this is a short summer"; var pattern =/(..)or(.)/g; if(pattern.test(text)){ console.log(RegExp.$1); // sh console.log(RegExp.$2); // t }
模式的局限性:
缺少一些高級正則表達式的特性,如不支持向后查找,命名的捕獲組(形如 \k<name> 引用之前名為 name 的捕獲組的字符串)等。
推薦專題: 《javascript正則表達式使用說明》
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助。
相關(guān)文章
Cropper.js進階之裁剪后保存至服務(wù)器實現(xiàn)詳解
這篇文章主要為大家介紹了Cropper.js進階之裁剪后保存至服務(wù)器實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-05-05JavaScript ES6中export、import與export default的用法和區(qū)別
這篇文章主要給大家介紹了JavaScript ES6中export、import與export default的用法和區(qū)別,文中介紹的非常詳細(xì),相信對大家學(xué)習(xí)ES6會有一定的幫助,需要的朋友可以參考借鑒,下面來一起看看吧。2017-03-03