吃透js中正則表達式

咱們在開發的過程當中總會碰到一些需求須要作字符串匹配,當遇到一些稍微複雜一點的匹配規則時,若是咱們對正則還不那麼清晰,咱們老是會去網上搜索一些現成的正則匹配,ctrl+c,ctrl+v。時間長了咱們對這種修修補補的方式不厭其煩。那麼今天就對正則表達式作足功夫,磨刀不誤砍柴工,首先推薦一個學習正則的一個可視化的工具網址: regexper.com,輸入正則規則便可生成匹配規則的流程圖。瞭解並吃透正則會爲咱們之後開發節省不少時間和精力,一勞永逸。先從最基本的概念開始吧,let go!git

元字符

概念:有特殊含義的特殊字符,eg: * + ? $ ^ . | \ ( ) { } [ ]等正則表達式

通用含義元字符

在大部分語言語境中表明同一種含義,以下表:數組

字符 含義
\t 水平製表符
\v 垂直製表符
\n 換行符
\r 回車符
\0 空字符
\f 換頁符
\cX Ctrl+X

其餘含義元字符

1. 字符類
  • 咱們可使用元字符[]來構建一個簡單的字符類
  • 所謂的類是指符合某些特性的對象,一個泛指,而不是特指某個字符
  • 表達式[abc]歸爲一類,表達式能夠匹配這些類的字符
2. 字符類取反
  • 咱們可使用元字符^來建立反向類/負向類
  • 反向類的意思是不屬於某個類的內容
  • 表達式[^abc]表示不是字符a或b或c的內容
3. 範圍類
  • 正則表達式還提供了範圍類
  • 咱們使用[a-z]來鏈接兩個字符表示從a到z的任意字符
  • 這是個閉區間也就包含a和z自己
4. 預約義類
  • 正則表達式提供了一些特殊字符表示自一組比較複雜的匹配規則,以下表:
字符 等價 含義
. [^\r\n] 除了回車符和換行符以外的全部字符
\d [0-9] 數字字符
\D [^0-9] 非數字字符
\s [\t\n\x0B\f\r] 空白符
\0 [^\t\n\x0B\f\r] 非空白符
\w [a-zA-Z_0-9] 單詞字符(字母數字下劃線)
\W [^a-zA-Z_0-9] 非單詞字符
5. 邊界
  • 正則表達式還提供了幾個經常使用的邊界匹配字符,以下表:
字符 含義
^ 以xxx開始
$ 以xxx結束
\b 單詞邊界
\B 非單詞邊界
6. 量詞
字符 含義
? 出現一次或0次(最多出現一次)
+ 出現一次或屢次(最少出現一次)
* 出現0次或屢次(任意次)
{n} 出現n次
{n, m} 出現n到m次
{n, } 至少出現n次

js正則的貪婪模式和非貪婪模式

  1. 貪婪模式:\d{3,6}匹配數字3到6次,那麼在匹配的過程當中會盡量多的的匹配。如:
'12345678'.replace(/\d{3,6}/, 'X')  // "X78"
複製代碼
  1. 非貪婪模式:在量詞後面加上 ? ,可讓正則表達式儘量少的匹配,也就是非貪婪模式。
'12345678'.replace(/\d{3,6}?/, 'X')  // "X45678"
複製代碼

分組

對一組正則規則加(),能夠對正則進行分組,bash

好比:對taoyouyou這組單詞匹配三次 taoyouyou{3} svg

可視化後能看到只是最後一個單詞u重複了3次,並無達到目的 (taoyouyou){3}
taoyouyou重複了3次

捕獲組引用

對字符串進行分組後,工具

捕獲組的編號是按照「(」出現的順序,從左到右,從1開始進行編號的 。學習

在replace方法中能夠經過$number(number表示捕獲組的編號)進行引用測試

在js表達式中分組引用經過RegExp對象暴露出來,ui

即經過RegExp.$number引用spa

例如實現2019-02-22 => 02/22/2019的轉化。

'2019-02-22'.replace(/(\d{4})-(\d{2})-(\d{2})/,'$2/$3/$1')   //  "02/22/2019"
複製代碼

反向引用

正則表達式中所定義的捕獲的反向引用指的是

將捕獲做爲正則表達式中可以成功匹配術語時的候選字符串

這種術語表示法是在反斜杆後面加一個要引用的捕獲數量。
捕獲組捕獲到的內容,不只能夠在正則表達式外部經過程序進行引用,也能夠在正則表達式內部進行引用,這種引用方式就是反向引用。反向引用的做用一般是用來查找或限定重複、查找或限定指定標識配對出現等等。 例如:([a-z])\1{2}也就表達連續三個相同的小寫字母。

忽略分組

不須要捕獲某些分組只須要在分組內加 ?: 就能夠了。 (?:taoyouyou).(ok)

前瞻

  • 正則表達式從文本頭部向尾部解析,文本尾部方向稱爲 「前」
  • 前瞻:正則表達式匹配到規則的時候,向前檢查是否符合斷言,後顧/後瞻方向相反
  • JavaScript不支持後顧
  • 符合和不符合某項斷言稱爲確定/正向匹配和否認/負向匹配
名稱 正則 含義
正向前瞻 exp(?=assert)
負向前瞻 exp(?!assert)
正向後顧 exp(?<=assert) JavaScript不支持
負向後顧 exp(?<!assert) JavaScript不支持

正則對象屬性

  • global: 是否全文匹配,默認false,匹配規則後面加g開啓
  • ignoreCase: 是否大小寫敏感, 默認false,匹配規則後面加i開啓
  • multiline: 多行搜索, 默認false,匹配規則後面加m開啓
  • lastIndex: 當前表達式匹配內容最後一個字符的下一個位置
  • source: 正則表達式的文本字符串 這幾個屬性都是隻讀屬性
reg=/\d/gmi
reg.global  // true
reg.ignoreCase  // true
reg.multiline  // true
reg.lastIndex  // 0
reg.source  // "\d"
複製代碼

對象方法

1. 正則test方法

RegExp.prototype.test(str)

  • 用於測試字符串參數中是否存在匹配正則表達式模式的字符串
  • 若是存在則返回true,不然返回false

須要注意的是:

var reg2=/\w/g;
複製代碼

進行reg2.test('ab')時,第三次會變成false 緣由:

while(reg2.test('ab')){
  console.log(reg2.lastIndex);
}
複製代碼

即進行test時,正則表達式的lastIndex會發生變化 輸出:1 2 表示第一個匹配上了、第二個匹配上了

2. 正則exec方法

RegExp.prototype.exec(str)

  • 使用正則表達式模式對字符串參數進行匹配搜索,並將更新全局對象屬性以反映匹配結果
  • 若是沒有匹配則返回null,不然返回一個結果數組: 屬性index(聲明匹配文本的第一個字符的位置), input(存放被檢索的字符串string) 數組自己: [與正則表達式相匹配的文本,與正則對象的第一個子表達式(分組)相匹配的文本, 與正則對象的第二個子表達式(分組)相匹配的文本,…… ]
var reg3=/\d(\w)(\w)\d/;    // 非全局搜索只能匹配到第一個結果
var reg4=/\d(\w)(\w)\d/g;   // 全局搜索匹配全文
var ts = '$1az2bb3cy4dd5ee'
var ret1= reg3.exec(ts)     // (3) ["1az2", "a", "z", index: 1, input: "$1az2bb3cy4dd5ee", groups: undefined]
console.log(reg3.lastIndex+'\t'+ret1.index+'\t'+ret1.toString())
// "0 1 1az2, a, z"
while(ret2 = reg4.exec(ts)){
  console.log(reg4.lastIndex+'\t'+ret2.index+'\t'+ret2.toString())
}
// "5 1 1az2, a, z"
// "11 7 1az2, a, z"
複製代碼

3. 字符串對象search方法

String.prototype.search(reg)

  • search方法用於檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的子字符串
  • 返回第一個匹配結果index,查不到返回-1
  • search()不執行全局匹配,它將忽略標誌g, 並老是從字符串的開始進行檢索

4. 字符串對象match方法

String.prototype.match(reg)

  • match方法將檢索字符串,以找到一個或多個與regexp相匹配的字符串
  • regexp是否具備標誌g對結果影響很大
非全局調用
  • 返回數組的第一個元素存放的是匹配文本,而其他的元素存放的是與正則表達式的子表達式匹配的文本
  • 除了常規的數組元素以外,返回的數組還含有2個對象屬性:index聲明匹配文本的起始字符在字符串的位置,input聲明對stringObject的引用
  • 全局調用的返回與正則表達式的exec方法相相似,即:[與正則表達式相匹配的文本,與正則對象的第一個子表達式(分組)相匹配的文本, 與正則對象的第二個子表達式(分組)相匹配的文本,…… ],數組有index和input屬性
全局調用
  • 若是regexp具備標誌g則match方法將執行全局檢索,找到字符串中的全部匹配子字符串
  • 沒有找到任何匹配的子串,則返回null
  • 若是找到了一個或多個匹配子串,則返回-一個數組
  • 數組元素中存放的是字符串中全部的匹配子串,並且也沒有index屬性或input屬性
var reg3=/\d(\w)(\w)\d/;    // 非全局搜索只能匹配到第一個結果
var reg4=/\d(\w)(\w)\d/g;   // 全局搜索匹配全文
var ts = '$1az2bb3cy4dd5ee'
var ret1= ts.match(reg3)   // (3) ["1az2", "a", "z", index: 1, input: "$1az2bb3cy4dd5ee", groups: undefined]   
console.log(reg3.lastIndex+'\t'+ret1.index)  // 0, 1
var ret2 = ts.match(reg4)  // (2) ["1az2", "3cy4"]
console.log(reg4.lastIndex+'\t'+ret2.index)   // 0 undefined
複製代碼

5. 字符串對象split方法

String.prototype.split(reg)

  • 咱們常用split方法把字符串分割爲字符數組 eg: 'a,b,c,d'.split(','); //["a", "b", "c", "d"]
  • 在一些複雜的分割狀況下咱們可使用正則表達式解決 eg: 'alb2c3d'.split(/\d/; //["a", "b", "c", "d"]

6. 字符串對象replace方法

String.prototype.replace

  • String.prototype.replace(str, replaceStr)
  • String.prototype.replace(reg, replaceStr)
  • String.prototype.replace(reg, function) function參數含義 function會在每次匹配替換的時候調用,有四個參數 一、匹配字符串 二、正則表達式分組內容,沒有分組則沒有該參數 三、匹配項在字符串中的index 四、原字符串
'a1b2c3d4e5'.replace(/\d/g, function(match, index, origin){
  return parseInt(match) + 1;
})  // "a2b3c4d5e6"

'a1b2c3d4e5'.replace(/(\d)(\w)(\d)/g, function(match, group1, group2, group3, index, origin){
  console.log(match)
  return group1 + group3;
})  
// 1b2
// 3d4
// "a12c34e5"

複製代碼
相關文章
相關標籤/搜索