js正則理論與實踐

學習正則表達式的時候,能夠說正則並非很難,可是就是老記不住語法規則,相信你們跟我也有一樣的發現吧,可是沒辦法,須要耐心的東西只能多啃幾遍了。javascript

正則表達式的做用

  • 數據驗證。
  • 複雜的字符串搜尋、替換。
  • 基於模式匹配從字符串中提取子字符串。

概述

正則表達式包括普通字符(例如,a 到 z 之間的字母)和特殊字符(稱爲「元字符」)。java

若要匹配這些特殊字符,必須首先轉義字符,即,在字符前面加反斜槓字符 \**。
例如,若要搜索 「+」文本字符,可以使用表達式 \+
可是大多數 特殊字符 在中括號表達式內出現時失去原本的意義,並恢復爲普通字符。正則表達式

構造函數

可以使用字面量也能夠用內置的構造函數:express

var regex = new RegExp('xyz', 'i');
var regex = new RegExp(/xyz/i); 
var regex = /xyz/i; 複製代碼

有一種狀況要注意:就是若是正則中出現了反斜槓 「\」 ,在用構造函數時建立正則對象時,要轉義, 好比: re = new RegExp("\\w+") // 這裏的 \ 要轉義,re = /\w+/ // 這樣就不須要轉義;
api

用於模式匹配的String方法

  • String.search()
    參數:要搜索的子字符串,或者一個正則表達式。
    返回:第一個與參數匹配的子串的起始位置,若是找不到,返回-1
    說明:不支持全局搜索,若是參數是字符串,會先經過RegExp構造函數轉換成正則表達式。如:

    var str="i am jay"; 
    var res=str.search("jay");
    console.log(res); //5
    console.log(str.search("hz"); //-1複製代碼

  • String.replace(),我的認爲是正則中最強大的api
    做用:查找並替換字符串。
    第一個參數:字符串或正則表達式,
    第二個參數:要進行替換的字符串,也能夠是函數。
    用法:

當第二個參數是字符串時,替換文本中的$字符有特殊含義:
數組

屬性 描述
$1,$2,…,$99 匹配第 1-99 個 分組裏捕獲的文本
$& 匹配到的子串文本
$` 匹配到的子串的左邊文本
$' 匹配到的子串的右邊文本
$$ 美圓符號

如:性能優化

'abc'.replace(/b/g, "{$$$`$&$'}")
// 結果爲 "a{$abc}c",即把b換成了{$abc}複製代碼
當第二個參數是函數時,如:

"1234 2345 3456".replace(/(\d)\d{2}(\d)/g, function (match, $1, $2, index, input) {
        console.log([match, $1, $2, index, input]);
        });    
// => ["1234", "1", "4", 0, "1234 2345 3456"]
// => ["2345", "2", "5", 5, "1234 2345 3456"]
// => ["3456", "3", "6", 10, "1234 2345 3456"] 複製代碼

  • String.match()
    參數:要搜索的子字符串,或者一個正則表達式。
    返回:一個由匹配結果組成的數組與是否有修飾符g有關

非全局檢索:若是沒有找到任何匹配的文本返回null;不然數組的第一個元素是匹配的字符串,剩下的是小括號中的子表達式,即a[n]中存放的是$n的內容。非全局檢索返回三個屬性:length 屬性;index 屬性聲明的是匹配文本的第一個字符的位置;input 屬性則存放的是被檢索的字符串 string。bash

全局檢索:設置標誌g則返回全部匹配子字符串,即不提供與子表達式相關的信息。沒有 index 屬性或 input 屬性。函數

如:性能

var string = "2017.06.27";
var regex1 = /\b(\d+)\b/;
var regex2 = /\b(\d+)\b/g;
console.log( string.match(regex1) );
console.log( string.match(regex2) );
// => ["2017", "2017", index: 0, input: "2017.06.27"]
// => ["2017", "06", "27"] 
複製代碼

  • String.split(),我的常常用到的一個api,簡單實用
    做用:把一個字符串分割成字符串數組,改變原字符串,與數組方法join對應
    參數:正則表達式或字符串,能夠有第二個參數,表示結果數組的最大長度 ,而且當正則使用分隔符時結果數組中是包含分隔符的。
    返回:子串組成的數組。

RegExp的方法

  • RegExpObject.exec(),比match強大
    參數:字符串。
    返回:

非全局檢索:與String.macth()非全局檢索相同,返回一個數組或null。

全局檢索:儘管是全局匹配的正則表達式,可是exec方法只對指定的字符串進行一次匹配。可是能夠反覆調用來實現全局檢索。在 RegExpObject 的lastIndex 屬性指定的字符處開始檢索字符串;匹配後,將更新lastIndex爲匹配文本的最後一個字符的下一個位置;再也找不到匹配的文本時,將返回null,並把 lastIndex 屬性重置爲 0。

var string = "2017.06.27";
var regex2 = /\b(\d+)\b/g;
var result;
while ( result = regex2.exec(string) ) {
console.log( result, regex2.lastIndex );
}
// => ["2017", "2017", index: 0, input: "2017.06.27"] 4
// => ["06", "06", index: 5, input: "2017.06.27"] 7
// => ["27", "27", index: 8, input: "2017.06.27"] 10 
複製代碼
  • RegExpObject.test(),匹配字串
    參數:字符串。
    返回:true或false。

  • RegExpObject.toString()
    返回:字符串

這兩個較簡單,就很少講了。

字符

| 指示在兩個或多個項之間進行選擇。相似js中的或,又稱分支條件
/ 正則表達式模式的開始或結尾。
\ 反斜槓字符,用來轉義。
- 連字符 當且僅當在字符組[]的內部表示一個範圍,好比[A-Z]就是表示範圍從A到Z;若是須要在字符組裏面表示普通字符-,放在字符組的開頭或者尾部便可。

. 匹配除換行符 \n 以外的任何單個字符。
\d 等價[0-9],匹配0到9字符。
\D 等價[^0-9],與\d相反。                                                                                                \s匹配空白符。與\S相反

\w 與如下任意字符匹配:A-Z、a-z、0-9 和下劃線,等價於 [A-Za-z0-9]。

\W 與\w相反,即 [^A-Za-z0-9]

限定符(量詞字符)

顯示限定符位於大括號 {} 中,幷包含指示出現次數上下限的數值;*+? 這三個字符屬於單字符限定符

{n} 正好匹配 n 次。
{n,} 至少匹配 n 次。
{n,m} 匹配至少 n 次,至多 m 次。
* 等價{0,}
+ 等價{1,}
? 等價{0,1}

注意:

  • 顯示限定符中,逗號和數字之間不能有空格,不然返回null!
  • 貪婪量詞*+:javascript默認是貪婪匹配,也就是說匹配重複字符是儘量多地匹配。
  • 惰性(最少重複匹配)量詞?:當進行非貪婪匹配,只須要在待匹配的字符後面跟隨一個?便可。如:

    var reg = /a+/;
    var reg2 = /a+?/;
    var str = 'aaab';
    str.match(reg); // ["aaa"]
    str.match(reg2); // ["a"]複製代碼

定位點(錨字符、邊界)

^ 匹配開始的位置。將 ^ 用做括號[]表達式中的第一個字符,則會對字符集求反。
$ 匹配結尾的位置。
\b 與一個字邊界匹配,如er\b 與「never」中的「er」匹配,但與「verb」中的「er」不匹配。
\B 非邊界字匹配。

標記

  • 中括號[] 字符組;標記括號表達式的開始和結尾。
    [...] 匹配方括號內任意字符。不少字符在[]都會失去原本的意義:[^...]匹配不在方括號內的任意字符;[?.]匹配普通的問號和點號。
    注意:反斜槓字符 \[]中仍爲轉義字符。若要匹配反斜槓字符,請使用兩個反斜槓 \\
    另外不要濫用字符組這個失去意義的特性,好比不要使用[.]來代替\:轉義點號,由於須要付出處理字符組的代價

  • 大括號{} 標記限定符表達式的開始和結尾。

  • 小括號() 標記子表達式的開始和結尾,主要做用是分組,對內容進行區分。

(模式) 能夠記住和這個模式匹配的匹配項(捕獲分組)。不要濫用括號,若是不須要保存子表達式,可以使用非捕獲型括號(?:)來進行性能優化
(?:模式) 與模式 匹配,但不保存匹配項(非捕獲分組)。
(?=模式) 零寬正向先行斷言,要求匹配與模式 匹配的搜索字符串。 找到一個匹配項後,將在匹配文本以前開始搜索下一個匹配項;但不會保存匹配項。
(?!模式) 零寬負向先行斷言,要求匹配與模式 不匹配的搜索字符串。 找到一個匹配項後,將在匹配文本以前開始搜索下一個匹配項;但不會保存匹配項。

可能會有點難懂,不過不要緊,來幾個例子就知道啥意思了

以下爲捕獲和非捕獲分組區別:

'13588884444'.replace(/(\d{3})(\d{4})(\d{4})/g, '$1****$3')
//=>  "135****4444"
'13588884444'.replace(/(\d{3})(?:\d{4})(\d{4})/g, '$1****$2')
//=>  "135****4444"
複製代碼

先行斷言(?=模式):x只有在y前面才匹配,必須寫成/x(?=y)/。 解釋:找一個x,那個x的後面有y。
先行否認斷言(?!模式): x只有不在y前面才匹配,必須寫成/x(?!y)/。 解釋:找一個x,那個x的後面沒有y。

如:對其後緊跟 "all" 的 "is" 進行全局搜索:

var str="Is this all there is";
var patern=/is(?= all)/g;
console.log(str.match(pattern));  //["is"]複製代碼

var s = "i am jay";
var p = /j(?!ay)/g;
s.match(p)
//null
複製代碼

  • 反向引用:主要做用是給分組加上標識符\n。
    \n 表示引用字符,與第n個子表達式第一次匹配的字符相匹配。

反向引用的例子,如要寫一個正則支持匹配以下三種格式: 

2016-06-12
2016/06/12
2016.06.12  

最早可能想到的正則是:

var regex = /\d{4}(-|\/|\.)\d{2}(-|\/|\.)\d{2}/; 
複製代碼

  其中 / 和 . 須要轉義。雖然匹配了要求的狀況,但也匹配 "2016-06/12" 這樣的數據。 

假設咱們想要求分割符先後一致怎麼辦?此時須要使用反向引用:  

var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
var string1 = "2017-06-12";
var string2 = "2017/06/12";
var string3 = "2017.06.12";
var string4 = "2016-06/12";
console.log( regex.test(string1) ); // true
console.log( regex.test(string2) ); // true
console.log( regex.test(string3) ); // true
console.log( regex.test(string4) ); // false 
複製代碼

注意裏面的 \1,表示的引用以前的那個分組 (-|\/|\.)。無論它匹配到什麼(好比 -),\1 都匹配那個一樣的具體某個字符。
咱們知道了 \1 的含義後,那麼 \2 和 \3 的概念也就理解了,即分別指代第二個和第三個分組。  

優先級順序

  1. \ 轉義符
  2. (), (?:), (?=), [] 括號和中括號
  3. *、+、?、{n}、{n,}、{n,m} 限定符
  4. 任何元字符^、$、\ 定位點和序列
  5. | 替換

實踐

看完介紹內容後能夠看看如下的例子,歡迎大佬們在評論區給出答案指定!!!

  1. 匹配 16 進制顏色值 
 要求匹配:
#ffbbad
#Fc01DF
#FFF
#ffE  


2.匹配時間  

以 24 小時製爲例。
要求匹配:
23:59
02:07  

3.匹配日期 

好比 yyyy-mm-dd 格式爲例。
要求匹配:
2017-06-10 

4.匹配 id 

 要求從

<div id="container" class="main"></div>
提取出 id="container"。

5.數字的千位分隔符表示法 

好比把 "12345678",變成 "12,345,678"。
可見是須要把相應的位置替換成 ","。  

6.字符串 trim 方法模擬

trim 方法是去掉字符串的開頭和結尾的空白符。 

7.匹配成對標籤 

要求匹配:
<title>regular expression</title>
<p>laoyao bye bye</p>
不匹配:
<title>wrong!</p> 

 8.將形如"a=1&b=2&a=3&b=4" 的字符串壓縮爲"a=1,3&b=2,4" ,(用replace)

9.test總體匹配某個字符串

10.IPV4 地址(優先級知識點) 

歡迎大佬們在評論區給出答案指定!!!,如想知道解析的也可在評論區提出。

相關文章
相關標籤/搜索