關於正則表達式的細枝末葉、易碎流年

本文原創:liuchendi正則表達式

1.正則表達式的基本概念

1.1 捕獲/匹配的概念

  1. 匹配:驗證當前字符串是否符合某個規則
  2. 捕獲:將字符串中符合規則的字符獲取到

1.2 正則表達式的建立

字面量方式建立數組

let reg = /元字符/修飾符bash

實例方式建立函數

letg reg = new RegExp('\d+',igm)//實例化建立正則的方式不須要加/(並不包括轉義斜槓\),並把修飾符以第二個參數的形式傳遞給實例測試


注意:字面量方式建立的正則表達式沒法識別變量,但實例方式建立的能夠

經過實例方式建立的正則,其中特殊元字符須要再加上一個\,由於字符串中的\也是表明轉義的意思,就會默認省略ui

let reg = new RegExp('\\b${cn}\\b')
複製代碼

正則表達式沒法識別連續的單詞中的字符或者數字,他會默認把他們當作一個一個單獨的字符去識別url

let reg = /[12-66]/ //表示1或2-6或5
複製代碼

回車打下的換行還自帶一個空格spa

當你要檢測字符串\d時prototype

let reg = /\\d/
reg.test('\\d')
//字符串中的斜槓首先就是一個轉義運算符,你要想測試\d
//字符串自己的\還要進行轉義
複製代碼

1.3 元字符的分類

  1. 特殊元字符(在正則表達式中有特殊意義的字符)
  2. 量詞元字符(限制元字符出現的連續次數)
  3. 其餘元字符
  4. 普通元字符

1.3.1 特殊元字符

  1. \    轉義元字符(把一些運算符轉換成原意)
  2. \d   出現0-9中的任意一位數字
  3. \D   出現除了0-9中的任意一位數字
  4. \w   匹配字母(包括大小寫)、數字、下劃線內的任意一個字符
  5. \W   匹配除字母(包括大小寫)、數字、下劃線之外任何一個字符
  6. \s   匹配空白符(空格 換行符)
  7. \S   匹配除空白符之外的任意一個字符
  8. \b   匹配單詞的邊界
  9. \B   匹配不在邊界的字符
  10. ^   匹配字符串的開頭(以什麼什麼開頭)
  11. $   匹配以什麼什麼結尾
  12. \n  匹配換行符
  13. .   匹配除換行符之外的其餘字符(至關於/N)

1.3.2 量詞元字符

量詞限制的是前面緊跟的某個字符出現的次數rest

  1. ?出現0~1次,無關緊要,至關於{0,1}
  2. . 出現0到屢次(無關緊要)能夠連續出現屢次。至關於 {0,}
  3. 加號 出現1到屢次(至少要出現1次)能夠連續出現屢次。至關於 {1,}
  4. {n} 連續出現n次 n表明次數
  5. {n,} 連續出現n到屢次 至少要連續出現n次 多了不限
  6. {n,m} 連續出現n到m次 至少要連續出現n次 最多連續出現m次
let reg = /^[a-z]$/
console.log(reg.test('aa')) // false  注意:這個是表示一個字母既是開頭又是結尾,而且是一個字母
複製代碼

1.3.3 其餘元字符

  1. |    x|y:匹配x或y中的任意一個字符,至關於[xy]
  2. []   [xyz]:匹配xyz中的任意一個字符,至關於x|y|z
  3. [^]  [^xyz]:匹配除xyz之外的任意一個字符
  4. [a-z][0-9]:匹配從a-z中的任意一個字母

1.3.4 正則中的修飾符

  1. g    global全局匹配
  2. i    ignoreCase忽略大小寫
  3. m    multiline多行匹配

1.4 正則中的小括號

正則當中小括號改變優先級

let reg = /^a|b$/       //以a爲開頭或者以b爲結尾
let reg3 = /^(a|b)$/    //至關於/^a$/或/^b$/
複製代碼

分組捕獲

分組引用

let reg = /^1(\d)\1\1$/
console.log(reg.test('1222')) // true
console.log(reg.test('1333')) // true
let reg2 = /^([a-z])([a-z])\2\1$/
console.log(reg2.test('abba')) // true
console.log(reg2.test('baba')) // false
複製代碼

在這裏如何計算他是第幾個分組,就從左往右看,看他的左括號是第幾個

1.5 正則中的中括號

  1. 中括號中部分元字符,表明的是原義 [?] [*] [+] [.]
  2. 中括號限制範圍[a-z]、[0-9]:若是是[9-0]會報錯,而且因爲正則表達式沒法識別連續的數字和單詞,因此[20-31]實際上識別的是2|[0-3]|1

2.正則表達式的經常使用方法

2.1 正則的捕獲

正則捕獲:將匹配到的內容,捕獲出來,做爲返回值返回給咱們。方法的位置:RegExp.prototype.exec()

他的返回值是一個數組,若是沒有捕獲到返回值爲null

  • ["2", index: 3, input: "abc23", groups: undefined]
  • 0: "2" 捕獲到內容
  • index: 3 捕獲到的起始索引位置
  • input: "abc23"  原始字符串
  • groups 命名匹配

index、groups、input都是是正則捕獲到的數組的自帶屬性,這個數組的長度爲1


2.2 正則的懶惰性

每次調用正則捕獲或者匹配的時候都是從索引0處開始捕獲的

let reg = /\d+/
let str = 'abc111 abc222 abc333'
reg.exec(str)// ["111", index: 3, input: "abc111 abc222 abc333", groups: undefined]

reg.exec(str)// ["111", index: 3, input: "abc111 abc222 abc333", groups: undefined]

reg.exec(str)// ["111", index: 3, input: "abc111 abc222 abc333", groups: undefined]
複製代碼

取消正則的懶惰性,修飾符g(global),會從上一次匹配或者捕獲成功的位置繼續向後查找

若是捕獲到結束邊界 會從頭再來

let reg = /\d+/g
let str = 'abc111 abc222 abc333'

console.log(reg.exec(str))
// ["111", index: 3, input: "abc111 abc222 abc333", groups: undefined]  test:true
   
console.log(reg.exec(str))
// ["222", index: 10, input: "abc111 abc222 abc333", groups: undefined]  test:true
    
console.log(reg.exec(str))
// ["333", index: 17, input: "abc111 abc222 abc333", groups: undefined]  testLtrue
    
console.log(reg.exec(str))
// null     test:false
    
console.log(reg.exec(str))
// ["111", index: 3, input: "abc111 abc222 abc333", groups: undefined]  test:true
複製代碼

2.3 正則實例下的屬性

lastIndex:他是正則實例上的一個屬性,下一次開始查找的起始索引

lastIndex的值能夠手動修改,可是若是沒有修飾符g的時候,修改不會起做用

reg.lastIndex = 9
複製代碼

不管是test仍是exec仍是混用,當加修飾符/g時,lastIndex屬性都是起決定性的因素。

let reg = /\d+/
reg.exec('abc111 abc222 abc333')    //111   index=3
reg.exec('a444 b555 c666')  //555
複製代碼

由於lastIndex是正則實例對象reg上的屬性,換字符串並不會影響他下面私有屬性的值

global屬性是用來標識正則是否有g修飾符的,返回值時true和false

multline屬性是否支持多行匹配

ignoreCase屬性是否忽略大小寫

sourse正則全部的元字符內容,不包括外界的兩個斜槓

2.4 字符串的match方法

match支持正則,在他的底層封裝的仍是exec,當沒有取消正則懶惰性的狀況下,他的返回值和exec相同,若是匹配不到返回值爲null

若是取消了正則的懶惰性,match會以數組的形式將捕獲到的結果一次性返回

2.5 正則的貪婪性

正則的貪婪性:每一次捕獲的時候老是捕獲到知足當前正則的最長內容

取消正則的貪婪性:量詞後面加?,按照最短的狀況進行匹配

let reg = /\d{2,8}?/g
複製代碼

2.6 分組捕獲

數組返回的第一項始終是整個大正則捕獲到的內容,若是有分組,會從第二項開始依次排列

let reg = /hello(\d+)/g
let str = 'hello2018 abc111 hello2019 abc222'
console.log(reg.exec(str))
// ["hello2018",2018, index: 0, input: "hello2018 abc111 hello2019 abc222", groups: undefined]
console.log(reg.exec(str))
// ["hello2019",2019, index: 0, input: "hello2018 abc111 hello2019 abc222", groups: undefined]
複製代碼

若是不加g,因爲match的底層就是exec,因此返回值和exec相同

若是加了g,因爲match是一次性捕獲,因此不能捕獲分組內容的

取消分組

在小括號的前面加上一個(?:)只匹配,不捕獲
let reg = /^(?:start|end)$/
複製代碼

2.7 分組引用

let reg = /^1(\d)\1$/
複製代碼

\1是對分組1的再次引用,這裏存在幾個小問題,其一是引用的分組表示兩個分組的內容相同,第二個是經過引用的分組經過RegExp.$拿不到

let reg = /^([a-z])\1([a-z]\1)$/
//aabb  ccdd
複製代碼

2.8 正向預查、負向預查

正向預查(?=元字符)    不會發生分組捕獲 負向預查(?!元字符)    不會發生分組捕獲

// 正向預查
// 捕獲 後面跟着3或者4的字母
let reg1 = /[a-z](?=3|4)/g
let str1 = 'a1 b2 c3 d4'
console.log(str1.match(reg1)) //["c", "d"]

// 負向預查
// 捕獲 後面跟着的不是3或者4的字母
let reg2 = /[a-z](?!3|4)/g
let str2 = 'a1 b2 c3 d4'
console.log(str2.match(reg2)) // ["a", "b"]
複製代碼

捕獲的不是預查的內容而是範圍內的內容

正向預查或者負向預查若是放在開頭的話,做用是限定後面的範圍\d,\w,[]

let reg11 = /^((?=3)\d)+$/
console.log(reg1.test('3333')) // true限定數字只能爲3

let reg2 = /^((?!4)\d)+$/g
console.log(reg2.test('1123123')) // true 限定數字裏不能有4
console.log(reg2.test('11234123')) // false
console.log(reg2.test('11234566')) // false
複製代碼

2.9 m修飾符(瞭解)

let reg = /^a.+b$/
let str = `a1b
a2b
a3b
`
reg.test(str)//false    由於沒有以a爲開頭,b爲結尾的
let reg1 = /^a.+b$/m

reg1.exec(str)//a1b     會把每一行都看做獨立的一行進行匹配 
reg1.exec(str)//a2b
reg1.exec(str)//a3b
複製代碼

2.10 字符串的replace、match、split均可以使用正則表達式

split

// let sss = '1a2b3c4'
// console.log(sss.split(/[a-z]/)) // [1, 2, 3, 4]
複製代碼

replace

replace的底層封裝的也是exec,至關於自動的對exec進行遍歷

let str = 'aaa2018 bbb2019'
let reg = /hello/   //若是加g,匹配到多少次,這個函數就會被執行幾回
//他會把exec捕獲到的值當作參數傳遞給這個函數
//這個函數的返回值就是replace捕獲到的內容所要替換的值
str.replace(reg,(...rest)=>{
    console.log(rest)
    return 'AA'
})
複製代碼

這個函數的返回值就是匹配到的內容要替換的新內容,有點相似於數組的map方法

let str2 = str.replace(/\d\b/g, a => a * 2)
//第一個參數是正則捕獲到的內容,因爲沒有用擴展運算符,因此穿入的直接是變量而不是數組
複製代碼

3.正則表達式的應用

3.1 時間字符串

方法一

let reg = \(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})\
str.replace(reg,`$1$2$3$4$5$6秒`)
str.replace(reg,function(...rest){
    return `${rest[1]}${rest[2]}${rest[3]}日`
})
複製代碼

方法二

let time2 = time.split(/[-\s:]/)//[2019,20,1,11,56,56]
let text = ['年','月','日',' ','時','分','秒']
//forEach拼接
複製代碼

方法三

let ary = time.match(/\d+/g)
let text = ['年','月','日',' ','時','分','秒']
ary.map()//遍歷修改
複製代碼

3.2 統計字符串中字母出現的次數

let newStr = str.split('').sort().join('')
let reg = /(\w)\1*/g
let obj = {}
newStr.replace(reg,function(){
   obj[rest[1]] = obj[rest[0].length] 
})
複製代碼

3.3 獲取url中的參數

let reg = /[?&]([^?&=]+)=([^?&=]+)/g
複製代碼

3.4 千分符

function format (num) {  
    var reg=/\d{1,3}(?=(\d{3})+$)/g;   
    return (num + '').replace(reg, '$&,');  
}
複製代碼

3.5 匹配手機號

let reg = /^1(36|58)\d{8}$/
複製代碼

3.6 驗證有效數字

let reg = /^[+-]?(\d|[1-9]\d+)(\.\d+)?$/
複製代碼

3.7 驗證範圍內數字23~66

拆分爲三段23-29,30-59,60-66

let reg = /(2[3-9])|([3-5]\d)|(6[0-6])/
複製代碼

3.8 驗證郵箱

第一部分能夠爲\w和. - ,可是. -不能做爲開頭和結尾i,不能連續

第二部分域名只能爲數字字母

let reg = /^\w+([-.]\w+)*@[\da-zA-Z]{2,6}(\.[a-z]{2,6}){1,2}$/
複製代碼

3.9 驗證類型

function testType(data){
    let str = Object.prototype.tostring.call(data)
    let reg = /\[object (\w+)\]/
    return str.exec(reg)[1].toLowerCase()
}
複製代碼
相關文章
相關標籤/搜索