正则表达式

114 阅读5分钟

1.匹配模式

匹配模式     描述

i           忽略大小写的匹配

g           全局搜索

// 获取所有匹配项,并忽略大小写
var a = 'test ademo A'
var reg = /a/i
var reg2 = /a/ig
a.match(reg) // ["a"]
a.match(reg2) // ["a", "A"]

2.基本元字符(所有符号都是元字符)

元字符

描述

.

匹配任意单个字符,除了回车和换行符之外的任意字符

|

逻辑或

[ ]

匹配中括号里面的一个字符

[ ^ ]

排除中括号里面的字符

-

定义一个范围区间 a-d 0-9等

\

转义符

\s

匹配任意空白字符(空格)

\S

匹配任意非空白字符(空格)

\d

匹配任意数字 [ 0-9 ]

\D

匹配任意非数字 [ ^0-9 ]

\w

匹配任意字母、数字、下划线 [ a-zA-Z_ ]

\W

匹配任意非字母、数字、下划线 [ ^a-zA-Z_ ]

\n

换行符

\r

回车符

^

匹配输入字行首

// example
// 操作符 .
let allStr = `
test demo all`

let arrReg = /^./
allStr.match(arrReg) // ["↵", index: 0, input: "↵test demo all", groups: undefined]
allStr.match(/./) // ["t", index: 1, input: "↵test demo all", groups: undefined]

// 操作符 |
let orStr = 'demo test example'
orStr.match(/demo|test|example/g) // ["demo", "test", "example"]
(/demo|test|example/).test(orStr) // true

// 操作符 [ ]   [ ^ ]
let oneStr = 'abestdwcacest==west'
oneStr.match(/[abc]est/g) // ["best", "cest"]
oneStr.match(/[^abc]est/g) // ["west"]

// 匹配字母
var regTest = /[a-t]est/g
regTest.test('aest') // true
regTest.test('est') // false
regTest.test('y') // false
(/\w/).test('ya123awd') // true

// 匹配数字和字母
var regTest1 = /[a-z0-9]/gi
regTest1.test('123456789') // true
regTest1.test('abcdefg') // true
regTest1.test('abcd1234efg') // true

// 匹配输入字行首 ^
var regTest2 = /^(a|b)/gi
var regTest3 = /^a/gi
regTest2.test('ac') // true
regTest2.test('dh') // false
regTest3.test('dh') // false

// 全局匹配数字
(/\d/g).test('123456') // true
(/\d/g).test('12asd3456') // true

// 全局匹配非数字字符串
(/\D/g).test('abc123456') // true
('abc123456').match(/\D/g) // ["a", "b", "c"]

// 全局匹配空格
(/\s/g).test('a bc 1') // true

// 全局匹配非空格
(/\S/g).test('a bc 1') // true
(/\S/g).test(' ') // false

3.量词(表示匹配多少个目标对象)

量词

描述

*

匹配前一个字符(表达式)0次或多次重复,等价于{ 0, }

匹配前一个字符(表达式)1次或多次重复,等价于{ 1, }

?

匹配前一个字符(表达式)0次或1次,等价于{0, 1}

{ n }

匹配前一个字符(表达式)n次重复

{ n, m }

匹配前一个字符(表达式)至少n次且至多m次

{ n, }

匹配前一个字符(表达式)n次或多次重复

// example

// 匹配某个字符串0次或者多个 *
var regTest = /ah*/g
('wabcabcah').match(regTest) // ["a", "a", "ah"]
var regTest1 = /a[a-z]*/g
// 正则表达式是贪婪的,即匹配满足给定要求的字符串的最长部分
('wabcabcah').match(regTest1) // ["abcabcah"]
// 我们需要最短怎么办 使用 ? 阻止贪婪模式
('wabcabcah').match(/a[a-z]*/) // ["abcabcah"]
('wabcabcah').match(/a[a-z]*?/g) // ["a", "a", "a"]
('wabcabcah').match(/a[a-z]*?/) // ["a"]
('abcdefg').match(/a[a-z]*/) // ["abcdefg"]
('abcdefg').match(/a[a-z]*?/) // ["a"]

// 匹配某个字符串一个或者多个 +
var regTest = /a+/g
('abcabc').match(regTest) // ["a", "a"]
var regTest = /ab+/g
('abcabcadcwac').match(regTest) // ["ab", "ab"]["a", "a"]

// 匹配某个字符数 { n, m}
(/ab{2,3}/).test('wwab') // false
(/ab{2,3}/).test('wwabb') // true
(/ab{2,3}/).test('wwabbbb') // true
(/ab{2,3}/).test('wwa') // false
('wwabbbb').match(/ab{2,3}/) // ["abbb", index: 2, input: "wwabbbb", groups: undefined]

 // 匹配某个字符数 { n, }
('wwabbbb').match(/ab{2,}/) // ["abbbb", index: 2, input: "wwabbbb", groups: undefined]
// 取消贪婪模式
('wwabbbb').match(/ab{2,}?/) // ["abb", index: 2, input: "wwabbbb", groups: undefined]
('wwabbbb').match(/ab{2}/) // ["abb", index: 2, input: "wwabbbb", groups: undefined]

// 匹配0次或1次  ?
(/abcd?e/).test('abcde') // true
(/abcd?e/).test('abce') // true

4.边界

边界

描述

^

匹配字符串的开头

$

匹配字符串的结尾

\b

匹配单词的边界

// example
// 匹配字符串的开头 ^
(/^test/).test('hello test') // false
(/^test/).test('test hello') // true
// 匹配字符串的结尾 $
(/test$/).test('hello test') // true
(/test$/).test('test hello') // false

// 匹配单词的边界 0右边是否不是单词
('hello test').match(/o\b/g) // ["o"]
(/o\b/g).test('hello test') // true

5.分组

分组

描述

()

将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。

\1

向后引用,匹配第一个子表达式 或者写成 $1

(?=pattern)

正向肯定预查,非获取匹配,预查不消耗字符

(?!pattern)

正向否定预查,非获取匹配,预查不消耗字符

(?<=pattern)

反向肯定预查,非获取匹配,预查不消耗字符

(?<!pattern)

反向否定预查,非获取匹配,预查不消耗字符

// example
// ()
('azzbcdefgaxxbc').replace(/a(z+|x+)/g, '--') // "--bcdefg--bc"
('azzbcdefgaxxbc').replace(/a(zz|xx)/g, '--') // "--bcdefg--bc"
('2021-01-28').replace(/(\d+)-(\d+)-(\d+)/, '$2/$3/$1') // "01/28/2021"
// 替换日期
('2021-01-28').replace(/(\d{4})-(\d{2})-(\d{2})/, '$2/$3/$1') // "01/28/2021"
// 匹配日期格式
// 简单版
(/^\d{4}-\d{2}-\d{2}$/).test('2021-01-28') // true
// 进化版 添加\1引用法,引用第一个分组表达式
(/^\d{4}(-|\/|\.)\d{2}\1\d{2}$/).test('2021-01-28') // true
(/^\d{4}(-|\/|\.)\d{2}\1\d{2}$/).test('2021/01-28') // false

6.预查

//  正向肯定预查 (?=pattern) 后面必须有某某某
// 在字符串中,数字下一位是字母的数字找出来
'1a2b3c4d5ee6f7g8hh9'.match(/\d(?=\w)/g) // ["1", "2", "3", "4", "5", "6", "7", "8"]
// 解释一开始左边额\d找到了数字1,然后进入正向预查,查到a是符合条件的,那么此时这个1就成立了
// 然后接着找a,a不符合\d,就接着找下一位2,2符合\d,接着正向预查判断后面一位的b符合要求,那么2成立
// 就是按照这样的方法循环下去的,知道查找完所有的字符串
'1a2b3c4d5ee6f7g8hh9'.replace(/\d(?=\w)/g, '-') // "-a-b-c-d-ee-f-g-hh9"

// 正向否定预查 (?!=pattern) 后面不能有某某某
// 这一串字符串里面不能每个字符串后面不能含有 \w 符合条件的只有最尾巴后面的,因为他后面没东西了
'1a2b3c4d5ee6f7g8hh9'.match(/\d(?!\w)/g) // ["9"]
'1a2b3c4d5ee6f7g8hh9'.replace(/\d(?!\w)/g, '-') // "1a2b3c4d5ee6f7g8hh-"

7.来点练习吧

// 请写一个校验以下格式的邮箱正则

// 123@qq.com 123@qq.com.cn ww@qq.com ww@qq.com.cn ww@163.com ww@163.com.cn
// 第一步写出 @前面的匹配 可以是数字和字母任意长度 并且是数字和字母开头的
/^[a-zA-Z\d]+/ // 可以匹配任何数字字母开头字符串
// 第二部匹配 @字符,和第一步组合起来
/^[a-zA-Z\d]+@/ // 组合起来了 xxx@格式
// 第三部我们需要匹配@后面的字符,截取到·之前的字符,因为有可能是数字和字符 /[a-zA-Z\d]+/
// 第三部:然后我们结合起来
/^[a-zA-Z\d]+@[a-zA-Z\d]+/
// 那我们先来验证一下 确保可行性
(/^[a-zA-Z\d]+@[a-zA-Z\d]+/).test('123@1a') // true
// 第四部我们写匹配 .com .com.cn 结尾的匹配
/(\.(com|cn)){1,2}$/
// 或者匹配任意结尾的 /(\.\w){1,2}$/
// 第四部组装起来
/^[a-zA-Z\d]+@[a-zA-Z\d]+(\.(com|cn)){1,2}$/
// 测试一下
/^[a-zA-Z\d]+@[a-zA-Z\d]+(\.(com|cn)){1,2}$/.test('123@qq.com.cn') // true
/^[a-zA-Z\d]+@[a-zA-Z\d]+(\.(com|cn)){1,2}$/.test('123@qq.com') // true
// 这里不是主要写邮箱 是为了如何去写一个正则校验的解析,一个思路