瞭解RegExp類型:
ECMAScript通過RegExp類型來支援Regex。 var expression=/pattern/flags;
Regex的模式(pattern)部分:
可以是任何簡單或複雜的Regex,可以包含字元類,限定符,分組,向前尋找,反向引用。 關於Regex中各種特殊字元(如 \,^,$,\w,\b 等)的含義可以參考 MDN Regex-特殊字元 的整理。這裡我們簡單介紹一下向前尋找和反向引用。
向前尋找:Regex向前使用一些字元而不移動這些字元的位置,分為正向前預搜尋也叫正向肯定尋找( x(?=y) )與負向前預搜尋也叫正向否定尋找( x(?!y) )。
反向引用:標識字串中可以提供的重複字元或字串,可以使用擷取的群組反向引用匹配。帶編號的反向引用 \number number是Regex中擷取的群組的序號位置。
1、運算式 \1~\9 解釋為反向引用而不是八進位代碼。 /\b(\w+)\s\1/.exec('s_ s_');//["s_ s_", "s_"]
2、如果多位運算式的第一個數字是8或者9(如 \80 或 \91 ),則該運算式將被解釋為文本。 /\b(\w+)\s\80/.exec('s_ 800');//["s_ 80", "s_"]
3、對於編號為 \10 或更大值的運算式,如果存在與該編號對應的反向引用,則將該運算式視為反向引用。否則將這些運算式解釋為八進位。
/(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、如果擷取的群組嵌套擷取的群組,擷取的群組確定的順序是內部從外到內,外部從左至右。來個代碼體會一下。
/\b(\w+x(x))\s(\1)/.exec('s_xx s_xxSTOP');//["s_xx s_xx", "s_xx", "x", "s_xx"]
5、如果Regex包含對未定義的群組成員的反向引用,則會發生分析錯誤,根據語言的不同Regex引擎將引發 ArgumentEXception 。對於javascript會返回null。/\b(\w+)\s\2/.exec('s_ 8');//null
反向引用執行個體代碼:擷取的群組捕獲到的內容不僅可以在Regex外部通過程式進行引用( RegExp.$n )也可以在Regex內部進行引用( \number ,這種引用方式就是反向引用)。
//表達連續三個相同的小寫,{2}應用在\1身上/([a-z])\1{2}/.exec('aaa');//["aaa", "a"]複製代碼//一道有意思的正則問題/(\w)((?=\1\1\1)(\1))/.exec('aa bbbb');//["bb", "b", "b", "b"]/*這裡擷取的群組有三個,$1為(\w)中的內容,$2為((?=\1\1\1)(\1))中的內容:需注意(?=\1\1\1)並不是擷取的群組而是Regex的判斷條件,x(?=y)表示匹配x僅僅當後面跟著y,判斷條件並不是匹配結果的一部分。所以現在$2的內容為(\1)即‘b'。$3就是\1的內容。返回的匹配項“bb”中的第一個'b'為"aa bbbb"中的第一個'b',第二個'b'為"aa bbbb"中的第二個'b'。*//(\w)(x(?=\1\1\1)(\1))/.exec('aa bxbbbcb');//["bxb", "b", "xb", "b"]//這裡$2的內容為(x(?=\1\1\1)(\1))中的內容即x(\1);//其實上面兩種模式可以簡化成/(\w)(?=\1\1\1)(\1)/表示匹配\w僅當該\w後後面跟著三個\1,然後擷取的匹配項為該\w且其後再緊跟著\1的字串。同理/(\w)x(?=\1\1\1)(\1)/複製代碼/(\w)((?=\1\1\1)(\2))/.exec('aa bbbbv');//["b", "b", "", ""]/*擷取的群組$2為((?=\1\1\1)(\2))中的內容,由於此時還未執行完擷取的群組$2處的匹配,所以\2表示""。$3即為\2的內容還是""。所以這條匹配被解釋為返回\w且其後緊跟3個該\w的字串,返回\w+''就只返回'b'了。*/
Regex的標誌位(flags)部分:
可以帶有一個或多個標誌,用以表明Regex的行為。
1、g:表示全域模式,模式將被應用於所有字串,而非在發現第一個匹配項時立即停止。 'cat mat bat'.replace(/.(?=at)/g,'A');//"Aat Aat Aat"
2、i:不區分大小寫入模式,在確定匹配項時忽略模式與字串的大小寫。 'cAt mat bAt'.replace(/a/gi,'B');//"cBt mBt bBt"
3、m:多行模式,在到達一行文本末尾時還會繼續尋找下一行中是否存在與模式比對的項。
var str='cat\nmat\nbat';str.replace(/at/gm,'AB');/*"cABmABbAB"*/
Regex中的元字元部分:
在模式中使用這些元字元時必須轉義,如果想要匹配的字串中包含這些字元,就需要對他們進行轉義。
( [ { \ ^ $ | ) ? * + . ] }//匹配"[bc]at"/\[bc\]at/.exec("xx[bc]at");//["[bc]at"]//匹配".at"/\.at/.exec("xx.at");//[".at"]
建立Regex:
字面量形式:形如 var expression=/pattern/flags;
RegExp建構函式:兩個參數(要匹配的字串模式,可選的標誌字串),不能把Regex字面量傳遞給建構函式,雖然即使這樣寫了也不會報錯。可以使用字面量定義的任何錶達式都可以使用建構函式來定義。如下:
var p=/[bc]at/;new RegExp('[bc]at');// /[bc]at/
1、當不傳任何參數或參數一為空白字串時, new RegExp();// /(?:)/ 或 new RegExp('');// /(?:)/ ,表示匹配 "" 但不記住匹配項( "" 其實就是 ":" 之後的空串,不記住x匹配項的規則為(?:x)),所以在匹配任何字串時都返回 [""] 。所以由此可以猜想一下javascript正則引擎內部機制應該是預設匹配 "" 且不記住該匹配項,除非顯式聲明在 ":" 之後的需要匹配的字串,加上 "(?:)" 顯式聲明不記住匹配項。
2、由於建構函式模式參數是字串,所以某些情況下(是指那些已經轉義過的字元)對字元進行雙重轉義(即在字面量形式的單重轉義再來一層轉義)。某些情況下當然也可以進行單重轉移( new RegExp('\w');// /w/ )。注意'\'比較特殊,在字串中也需要進行轉義。
var p=/\\n/;//轉義\,字元"\"在字串中常需要被轉義為"\\"p.exec("\\nxx");//["\n"]var p=new RegExp("\\\\n");// /\\n/ 如果想獲得Regex字面量為/\\n/,需要在Regex中再來一層轉義p.exec('\\nxx');//["\n"] 注意被匹配的字串'\nxx'中\n的\也被轉義了new RegExp('\\n').exec("\n");// [""]/*RegExp('\\n')返回/\n/,即意思匹配分行符號*/new RegExp('\n').exec("\n");//[""]/*new RegExp('\n')返回// ,表示並沒有進行轉義,而是返回字面量//,意思匹配分行符號*/
3、下面給出一些單重,雙重轉義模式的參考:第幾次轉義在表中已標出,單代表第一次轉義,雙代表在已經有的轉義的基礎上再進行的轉義。
RegExp的執行個體屬性:
通過執行個體的屬性可以擷取有關模式的各種資訊
global :布爾值,表示是否設定了g標誌。
ignoreCase :布爾值,表示是否設定了i標誌。
multiline :布爾值,表示是否設定了m標誌。
lastIndex :整數,表示開始搜尋下一個匹配項的字元位置,從0算起。前提是設定g標誌時才會有用。
source :Regex的字串標誌,按照字面量形式而非建構函式中的字串模式返回字串。
new RegExp('\\\\w');// /\\w/ 返回自面量形式Regexnew RegExp('\\\\w').source;// "\\w" 字串
RegExp的執行個體方法:
exec():該方法是專門為擷取的群組而設計的,參數為要匹配的字串,返回包含第一個匹配項資訊和可能有的擷取的群組的數組,若未匹配到返回 null 。(返回的雖然是 Array 的執行個體,但還包含兩個額外的屬性: index 表示匹配項在字串中的位置, input 表示應用Regex的字串)
var arr=new RegExp('\\\\(w)').exec('\\w');// ["\w", "w"]arr;// ["\w", "w"]arr.index;//0arr.input;// "\w" 即exec()裡的內容
exec() 和 match() 方法的區別:
1、對於 exec() 而言,即使在模式中設定了全域標誌g,它每次也只返回一個匹配項;字串的 match() 方法在設定g的時候可以返回全部匹配項而沒有擷取的群組且返回的數組沒有index和input屬性。
2、對於exec()而言可以返回擷取的群組,但match()在沒有全域g標誌時才能返回擷取的群組,此時match()返回的數組有index和input屬性。
//返回全域匹配項示範比較var arr='ababcdab'.match(/ab/g);// ["ab", "ab", "ab"]arr.index; // undefinedarr.input; // undefined/ab/g.exec('ababcdab');// ["ab"]//擷取的群組示範比較,match()方法和有無設定全域g標誌有關'ababcdab'.match(/a(b)/g);// ["ab", "ab", "ab"]var arr='ababcdab'.match(/a(b)/);// ["ab", "b"]arr.index;// 0arr.input;// 'ababcdab'/a(b)/g.exec('ababcdab');// ["ab", "b"]
3、所以在選擇使用方法的時候要先考慮好側重該方法的哪方面功能,在不設定全域標誌g的情況下,在同一個字串上多次調用exec()則總是返回第一個匹配項的資訊,而在設定全域標誌的情況下,每次調用exec()則都會在字串中沿著上次尋找的位置往後繼續尋找新的匹配項。
//未設全域,每次從頭開始尋找var p=/a/;var str='ababa';var a=p.exec(str);// ["a"];var b=p.exec(str);// ["a"];a==b;// falsea.index==b.index;// true//設定全域,沿著上次位置繼續尋找新匹配var p=/a/g;var str='ababa';var a=p.exec(str);// ["a"]a.index;// 0var b=p.exec(str);// ["a"]b.index;// 2
test():接收字串參數,在模式與字串參數匹配情況下返回 true ,否則返回 false 。常被用在 if() 中當判斷條件。
var text="000-000-000";var p=/((\d{3})-)\1*\2/; if(p.test(text)){ console.log('匹配成功');}
RegExp 執行個體繼承 Object 的 toLocaleString() 和 toString() 方法都會返回Regex的字面量形式的字串,與如何建立Regex的方式無關。 valueOf() 則返回Regex字面量本身。
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的建構函式屬性:
建構函式本身包含一些屬性(靜態屬性),這些屬性適用於範圍中的所有運算式,並且基於所執行的最近一次Regex操作而變化。有長屬性名稱(如下代碼)和短屬性名稱(即$首碼形式,由於這些符號大多不是有效ECMAScript標識符,所以不能直接在 RegExp 建構函式上以 "." 的方式訪問,而要通過方括弧文法來訪問)兩種方式訪問這些屬性
/(.)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個用於儲存擷取的群組的建構函式屬性,訪問文法是 RegExp.$n ,其中n取值1~9,用於擷取第n個匹配的擷取的群組。在調用 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 }
模式的局限性:
缺少一些進階Regex的特性,如不支援向後尋找,命名的擷取的群組(形如 \k<name> 引用之前名為 name 的擷取的群組的字串)等。
推薦專題: 《javascriptRegex使用說明》
以上就是本文的全部內容,希望對大家的學習有所協助。