正則表達式(Regular Expression)是計算機科學的一個概念。 正則表達式使用單個字符竄來描述、匹配一系列符合某個句法規則的字符竄。 在不少文本編輯器裏, 正則表達式一般用來被檢索替換哪些符合某個模式的文本。正則表達式
JavaScript經過內置對象 RegExp支持正則表達式, 有兩種方式建立正則表達式對象, 若是咱們想匹配字符竄中<%xxx%>兩個百分號分割的字符竄能夠這麼寫。數組
var regExp = new RegExp('<%[^%>]+%', 'g');
var regExp = /<%[^%>]%>/g;
最後的g表明全局, 還有幾個修飾符編輯器
RegExp實例對象有五個屬性函數
除了正則表達式編譯爲內部格式從而使執行更快的compile()方法, 對象還有兩個咱們經常使用的方法。測試
正則表達式讓人望而卻步的一個重要緣由就是轉譯字符太多, 組合很是多, 可是正則表達式的元字符(在正則表達式中具備特殊意義的專用字符,能夠用來規定其前導字符)並很少this
() [] {} \ ^ $ | ? * + .
並非每一個元字符都有特定的意義,在不一樣的組合中元字符有不一樣的意義, 分類看一下prototype
通常狀況下正則表達式一個字符(轉譯字符算一個) 對應字符竄一個字符,表達式 abt 的含義3d
ab水平製表符
可是咱們可使用元字符[]來構建一個簡單的類, 所謂類是指,符合某些特徵的對象, 是一個泛指,而不是特指某個字符了, 咱們可使用表達式[abc], 把字符a或b或c歸爲一類,表達式能夠匹配這類的字符。code
元字符[]組合能夠建立一個類,咱們還可使用元字符^建立反向類/負向類,反向類的意思是不屬於XXX類的內容, 表達式1表示不是字符a或b或c的內容。regexp
按照上面的說明若是但願匹配單個數字那麼表達式是這樣的
[0123456789]
若是是字母那麼。。。 好麻煩, 正則表達式還提供了範圍類,咱們可使用x-y來鏈接兩個字符表示從x到y的任意字符, 這是個閉區間, 也就是說包含x和y自己, 這樣匹配小寫字母就很簡單了。
[a-z]
剛纔使用正則咱們建立了幾個類,來表示數字,字母等,但這樣寫很麻煩,正則表達式爲咱們了幾個經常使用的預約義類來匹配常見的字符。
字符 | 等價類 | 含義 |
---|---|---|
. | [^rt] | 除了回車符和換行符以外的全部字符 |
d | [0-9] | 數字字符 |
D | [^0-9] | 數字字符 |
s | [\t\n\x0B\f\r] | 空白符 |
S | [^t\n\x0B\f\r] | 非空白符 |
w | [a-zA-Z_0-9] | 字母,數字,下劃線 |
W | [^a-zA-Z_0-9] | 非字母,數字,下劃線 |
有了這些預約義類, 寫一些正則就很方便了, 好比咱們但願匹配一個 ab + 數字 + 任意字符的字符竄, 就能夠寫了abd.
能夠把正則表達式,想象成一種模式,字符竄匹配正則表達式定義的模式的結果
string.match(regExpPattern)
正則表達式還提供了幾個經常使用的邊界匹配字符。
字符 | 含義 |
---|---|
^ | 以xxx開頭, ^ 開頭的匹配參照對象是整個字符竄 |
$ | 以xxx結尾, $ 結尾的匹配參照對象也是整個字符竄 |
b | 單詞邊界, '-'也是單詞邊界! |
B | 非單詞邊界 |
^ 開頭的匹配參照對象是整個字符竄, $ 結尾的匹配參照對象也是整個字符竄, 限制的是整個字符竄。 var regExpPattern = /^h\dm/g; 'h2m h4m h2m'.match(regExpPattern); // h2m, 記住這是以整個字符竄去匹配的 //同理 var regExpExpPattern = /h\dm$/g; 'h2m h4m h4m'.match(regExpPattern); // h4m //使用場景 手機號匹配 '13423454234'.match(/^1\d{10}$/g)
以前,介紹的方法都是一一匹配,若是但願匹配一個連續20次數字的字符竄難道咱們須要寫成這樣?
\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d\d..
爲此正則表達式引入了一些量詞
字符 | 含義 |
---|---|
? | 出現零次或一次(最多出現一次) |
+ | 出現一次或屢次(至少出現一次) |
* | 出現零次或屢次(任意次) |
{n} | 出現n次 |
{n,m} | 出現n到m次 |
{n,} | 至少出現n次 |
{,m} | 最多出現m次 |
var regExp = /w+\bBryon/ regExp.test('hi Bryon'); // true regExp.test('Welcome Byron'); // true regExp.test('Byron'); //false //匹配帶有3到1個小數的數字 var reg = /\d+\.d{1,3}
看了量詞的介紹,也許愛思考的同窗會想到關於匹配原則的一些問題, 好比{3,5} 這個量詞, 要是在句子中出現了十次, 那麼他是每次匹配三個仍是五個,反正3,4,5都知足3~5的條件。
量詞在默認下是儘量多的匹配的,也就是你們常說的貪婪模式。
// ['12345','6789']; '12345679'.match(/\d{3,5}/g);
既然有貪婪模式,那麼確定會有非貪婪模式,讓正則表達式儘量少的匹配,u額就是說一旦成功匹配再也不繼續嘗試,作法很簡單, 在量詞後加上?便可
//['123','456','789'] '123456789'.match(/\d{3,5}?/g);
有時候但願使用量詞的時候匹配多個字符,而不是像上面例子只是匹配一個,好比但願匹配Byron出現20次的字符竄,寫成Byron{20}的話匹配的是Byro+n出現20次。
//寫成Byron{20}的話匹配的是Byro+n出現20次。 /Byron{20}/g
怎麼把Byron做爲一個總體呢? 使用()就能夠達到此目的,在正則中成爲分組。
//分組在regExp.exec(stringObj)中會單獨顯示在返回結果中。 (Byron){20}
或 |
若是但願匹配Byron或Casper出現20次該怎麼辦呢? 可使用字符| 達到或的功效
(Byron|Casper){20}
使用分組的正則表達式會把匹配項也放到分組中,默認是按數字編號分發的,能夠根據編號得到捕獲的分組內容,這在一些但願具體操做第幾個匹配項的函數中頗有用。
// Group 1 : Byron , Group 2: ok (Byron).(ok)
分組嵌套
若是有分組嵌套的狀況,外面的組的編號靠前
// group 1: (^|%>)[^\t]*, Group 2: (^|%>) ((^|%>)[^\t]*)
忽略分組
有時候咱們不但願捕獲某些分組,只須要在分組內加上?: 就能夠了, 這並不意味着該分組內容不屬於正則表達式,只是不會給這個分組加編號而已。
(?:Bryon).(ok)
表達式 | 含義 |
---|---|
exp1(?=exp2) | 匹配後面是exp2的exp1 |
exp1(?!exp2) | 匹配後面不是exp2的exp1 |
var regExp = /good(?=Byron)/; regExp.exec('goodByron123'); // ['good'] regExp.exec('goodCapser123'); // null
經過上面例子能夠看出exp1(?=exp2)表達式, 但只有其後面內容是exp2的時候纔會匹配,也就是兩個條件,exp1(?!exp2)比較相似。
該方法用於測試字符竄參數中是否匹配正則表達式模式,若是存在則返回true,不然返回false。
var reg = /\d+\.\d{1,2}$/g; reg.test('123.45'); // true reg.test('0.2'); // true reg.test('a.34'); //false reg.test('34.5678'); //false
//判斷手機號是否正確 function isPhoneNum(phoneNum) { var phoneNumberTester = /^1\d{10}$/; return phoneNumberTester.test(phoneNum); }
該方法用於正則表達式模式在字符竄中運行查找,若是exec()找到匹配的文本,則返回一個結果,不然返回null
除了數組元素和length屬性以外, exec()方法返回對象還包括兩個屬性。
非全局調用
調用非全局的RegExp對象的exec()時,返回數組的第一個元素是與正則表達式相匹配的文本,第二個元素是與RegExpObject的第一個子表達式相匹配的文本(若是有的話), 第三個元素時與RegExp對象的第二個子表達式相匹配的文本(若是有的話),以此類推。
全局調用
調用全局的RegExp對象的exec()時,它會在RegExp實例的lastIndex屬性指定的字符處開始檢索字符竄string
var reg = /\d/g; var r = reg.exec('a1b2c3'); console.log(r); console.log(reg.lastIndex); // 2 r = reg.exec('a1b2c3'); console.log(reg.lastIndex); // 4
var reg = /\d/g; while (r = reg.exec('a1b2c3')) { console.log(r.index + ':' + r[0]) } //1:1 , 3:2, 5:3
search()方法用於檢索字符竄中指定的子字符串,或檢索與正則表達式相匹配的子字符竄。
search()方法不執行全局匹配,它將忽略標誌g, 它同時忽略正則表達式對象的lastIndex屬性,而且老是從字符竄的開始進行檢索,這意味着它老是返回字符竄的第一個匹配的位置。
match()方法將檢索字符竄,以找到一個或多個與regexp匹配的文本。但regexp是否具備標誌g對結果影響很大。
非全局調用
若是regexp沒有標誌g,那麼match()方法就只能在字符竄中執行一次匹配。若是沒有找到任何匹配的文本,match()將返回null。不然它將返回一個數組,其中存放了與它找到的匹配文本有關的信息。
該數組的第一個元素存放的是匹配文本,而其他的元素存放的是與正則表達式的子表達式匹配的文本。除了這些常規的數組元素以外,返回的數組還含有兩個對象屬性。
關於string對象的replace方法, 咱們最經常使用的是傳入兩個字符竄的作法,但這種作法有個缺陷,只能replace一次。
'abcabcabc'.replacce('bc', 'X') //aXabcabc
replace方法的第一個參數還能夠傳入RegExp對象,傳入正則表達式可使replace方法更增強大靈活
'abcabcabc'.replace(/bc/g, 'X'); //aXaXaX 'abcabcabc'.replace(bc/gi, 'X'); // aXaXaX
若是replace方法的第一個參數傳入的是帶分組的正則表達式,咱們在第二個參數中可使用$1...$9來獲取相應分組內容, 好比但願把字符竄1<%2%>34>%567%>89的<%x%>換爲$#x#$, 咱們能夠這樣
'1<%2%>34>%567%>89的<%x%>'.replace(/<%(d+)%>)/g, '@#$1#@');
// 1@#2#@34@#567#@89
固然還有不少方式能夠達到這一目的,這裏只是演示一下利用分組內容,咱們在第二個參數中使用@#$1#@, 其中$1表示被捕獲的分組內容弄, 在一些js模板函數中能夠常常見到這種方式替換字符竄。
能夠經過修改replace方法的第二個參數,使replace更增強大,在前面的介紹中,只能把全部匹配替換爲固定內容,但若是我但願把一個字符竄中全部數字,都用小括號包起來該怎麼弄?
'2398sdadads1smdsa3mmm23mmmbb'.replace(/\d+/g, function(matchedStr, groupContent$, index, strObj ) { return '(' + matchedStr + ')'; })
把replace方法的第二個參數傳入一個function,這個function會在每次匹配替換的時候調用,算是個每次替換的回調函數,咱們使用了回調函數的第一個參數,也就是匹配內容,其實回調函數一共有四個參數。
例子
'2398rsjdhahd2131kksdajdj23'.replace(/\d+/g, function(matchedSubStr,index, strObj) { console.log(matchedSubStr + '\t' + index + '\t' + strObj); return '(' + matchedSubStr +')'; }) //2398 0 2398rsjdhahd2131kksdajdj23 //2131 12 2398rsjdhahd2131kksdajdj23 //23 24 2398rsjdhahd2131kksdajdj23
這是沒有分組的狀況,打印出來的分別是匹配內容、匹配項index和原字符竄,看個有分組的。
'<%1%><%2%><%3%>'.replace(/<%([^%>]+)%>/g, function(matchedStr, group, index, thisStrObj) { console.log(matchedStr + '\t' + group + '\t' + index + '\t' + thisStrObj); return group; }) //<%1%> 1 0 <%1%><%2%><%3%> //<%2%> 2 5 <%1%><%2%><%3%> //<%3%> 3 10 <%1%><%2%><%3%> //"123"
使用split方法把字符竄分割爲字符數組
'a,b,c,d'.split(','); // ['a','b','c','d']
和replace方法相似,在一些複雜的分割狀況下咱們可使用正則表達式解決
'a1b2c3d'.split(/\d/); // ['a','b','c','d']