1.编写正则的两种方法
- 字面量创建 (注意//里面的是元字符,字面量创建正则不能使用变量,会当作字符串解析)
let reg = /\d/g
\s - 构造函数模式创建(注意,里面的是字符串,想要变成元字符必须用 \ 进行转意,可以使用变量)
let reg = new RegExp("\\d", "g")
###2.元字符和修饰符
1.量词元字符(设置出现的次数)
- * 表示0到多次
- +表示1到多次
- ?0次或1次
?问号是量词元字符;
如果?左边是普通元字符,表示让普通元字符出现0到1次;
如果?左边是量词元字符,表示取消这个量词符的贪婪性;
- {n} 出现n次
- {n,}出现n到多次
- {n, m}出现n到m次
2.特殊元字符(单个或者多个组合在一起代表特殊含义)
单个
- \ 转义字符(普通转特殊,特殊转普通)
let reg1 = /^1.1$/ //表示以1开头,以1结尾中间是除\n(换行符)以外的任意一个字符
let reg2 = /^1\.1$/ //表示1.1
console.log(reg1.test('1.1')) //true
console.log(reg1.test('101')) //true
console.log(reg1.test('11')) //false
console.log(reg2.test('1.1')) //true
console.log(reg2.test('101')) //false
console.log(reg2.test('11')) //false
let str = '\\d' ('\d' === 'd', '\\d' === '\d')
console.log(/^\d$/.test(str)) //false
console.log(/^\\d$/.test(str)) //true
- . 除\n(换行符)以外的任意字符
- ^以哪一个元字符作为开始
let reg = /^\d/
console.log(reg.test('2020fjl')) //true
console.log(reg.test('fjl2020')) //false
console.log(reg.test('fjl2020fjl')) //false
- $以哪一个元字符作为结束
let reg = /\d$/
console.log(reg.test('2020fjl')) //false
console.log(reg.test('fjl2020')) //true
console.log(reg.test('fjl2020fjl')) //false
- ^ &以指定字符开始和结束
let reg = /^\d$/
console.log(reg.test('2020fjl')) //false
console.log(reg.test('fjl2020')) //false
console.log(reg.test('fjl2020fjl')) //false
console.log(reg.test('2020')) //false
组合
- \n 换行符
- \d 0~9之间的一个数字
- \D 非0~9之间的一个数字(与小写意思相反)
- \w 数字,字母,下划线的任意一个字母
- \W 非数字,字母,下划线的任意一个字母(与小写意思相反)
- \s 一个空白字符(包含空格,制表符,换行符)
- \t 一个制表符(一个TAB键,四个空格)
- \b 匹配一个单词边界
- \B 匹配一个非单词边界
- x | y x或者y中的任意一个
let reg = /^18|29$/
console.log(reg.test('18')) //true 18或者19
console.log(reg.test('29')) //true 18或者19
console.log(reg.test('129')) //true 8或9
console.log(reg.test('189')) //true 8或9
console.log(reg.test('1829')) //true 18开头或者19结尾
console.log(reg.test('829')) //true 18开头或者19结尾
console.log(reg.test('182')) //true 18开头或者19结尾
//直接写x|y会有很严重的优先级的问题,一般与()连用
let reg = /^(18|29)$/
console.log(reg.test('18')) //true
console.log(reg.test('29')) //true
console.log(reg.test('129')) //false
console.log(reg.test('189')) //false
console.log(reg.test('1829')) //false
console.log(reg.test('829')) //false
console.log(reg.test('182')) //false
- [xyz] x或者y或者z中的一个字符
- [^xyz] 除了x,y或者z以外的任意字符
- [A-z] 指定A-Z或a-z之间的任意字符
- [a-z] 指定a-z之间的任意字符
- [^a-z] 指定除a-z之间的任意字符
//[]出现的字符有时候代表本身含义 ("?","+","*","\b"......)
let reg = /^[@+]$/
console.log(reg.test('@+')) //false
console.log(reg.test('@')) //true
console.log(reg.test('+')) //true
//[]中不存在多位数
let reg = /[18]/
console.log(reg.test('1')) //true
console.log(reg.test('8')) //true
console.log(reg.test('18')) //false
- ()正则中的分组
//()作用1:分组
let reg = /^(18|29)$/
console.log(reg.test('18')) //true
console.log(reg.test('1')) //false
//()作用2:捕获 (捕获到一个数组,里面有每一个小分组)
let reg = /^(\d{6})(\d{8})(\d{3})(\d{1}|x)$/
console.log(reg.exec('50023319999999999x')) //["50023319999999999x", "500233", "19999999", "999", "x", index: 0, input: "50023319999999999x", groups: undefined]
//作用3 分组引用
//()\n 表示出现n个分组里面的内容
//匹配类似moon, good格式的单词
let reg = /^[A-z]([A-z])\1[A-z]$/
console.log(reg.test('good')) //true
console.log(reg.test('deep')) //true
console.log(reg.test('some')) //true
4.正则捕获具有贪婪性
let reg = /\d+/g
console.log('fu2020jun2021ling'.match(reg)) //["2020", "2021"]
//思考:我匹配的是一个或多个数字,那为什么不是['2','0','2',.....],原因是正则具有贪婪性,会最多的进行匹配
//取消贪婪性
//1.取消+号
//2.在+号右边添加?
let reg = /\d+?/g
console.log('fu2020jun2021ling'.match(reg)) //["2", "0", "2", "0", "2", "0", "2", "1"]
- (?:)只匹配不捕获
- (?=)正向预查
- (?!)负向预查
3.普通元字符(代表本身含义,除了以上字符剩下的都是普通字符)
4.修饰符(img)
- i => ignoreCase 忽略单词大小写匹配
- m => multiline 可以进行多行匹配
- g => global 全局匹配
5.正则方法总结
1.test()
//test() 方法用于检测一个字符串是否匹配某个模式。如果字符串中有匹配的值返回 true ,否则返回 false。
//若正则带全局修饰符g时,会改变lastIndex属性的值
let reg = /\d/
console.log(reg.test('111')) //true
console.log(reg.test('abc')) //false
//test()方法也可以进行捕获
//test可以捕获到大正则里面的小正则,从$1到$9,可以匹配九个大正则里面的小分组
let str = '{0}年{1}月{2}日'
let reg = /\{(\d){1,2}\}/g
console.log(reg.test(str)) //true
console.log(RegExp.$1) //0
console.log(reg.test(str)) //true
console.log(RegExp.$1) //1
console.log(reg.test(str)) //true
console.log(RegExp.$1) //2
console.log(reg.test(str)) //false
console.log(RegExp.$1) //2 存储的是上次捕获的值
let str = '{0}年{1}月{2}日'
//reg为匹配上面完整字符的正则
let reg = /\{(\d){1,2}\}[\u4E00-\u9FA5]\{(\d){1,2}\}[\u4E00-\u9FA5]\{(\d){1,2}\}[\u4E00-\u9FA5]/g
console.log(reg.test(str)) //true
console.log(RegExp.$1) //0
console.log(RegExp.$2) //1
console.log(RegExp.$3) //2
2.exec()
exec捕获(捕获的结果为一个null[匹配失败]或者一个数组[匹配成功])
//不加全局修饰符g时
let reg = /(\d+)\w/
console.log(reg.exec('fu2020jun2021ling'))
//0: "2020j", 本次捕获的内容
//1: 2020 (若有小分组,则会有小分组捕获的结果)
//groups: undefined,
//index: 2, 捕获内容的起始位置-
//input: "fu2020jun2021ling", 原始字符串
//length: 2
console.log(reg.exec('fu2020jun2021ling'))
//结果与上一次相同
//加了全局修饰符g时
let reg = /(\d+)/g
console.log(reg.exec('fu2020jun2021ling'))
//0: "2020j", 本次捕获的内容
//1: 2020 (若有小分组,则会有小分组捕获的结果)
//groups: undefined,
//index: 2, 捕获内容的起始位置-
//input: "fu2020jun2021ling", 原始字符串
//length: 1
console.log(reg.exec('fu2020jun2021ling'))
//0: "2021l", 本次捕获的内容
//1: 2021 (若有小分组,则会有小分组捕获的结果)
//groups: undefined,
//index: 9, 捕获内容的起始位置-
//input: "fu2020jun2021ling", 原始字符串
//length: 1
console.log(reg.exec('fu2020jun2021ling'))
//null
// 每执行一次exec,只能捕获到第一个符合规规则的内容,但是默认情况下,执行一百遍也只会拿到第一个匹配的内容,其余的则捕获不到(正则捕获的懒惰性:默认只捕获第一个)
// 因为正则属性lastIndex(当前正则下一次匹配的起始索引位置)的影响,默认情况下lastIndex不改变,一直为0,所以每一次都从起始位置开始找。
// 要想内一个捕获的内容不同,就需要全局g属性,他会使lastIndex的值改变,当匹配到最后一个时,再次执行exec则会返回null,lastIndex变成0,然后以此循环。
自己封装一个可以捕获所有匹配成功内容的方法execAll()
这个方法也等同于match方法,内置结构原理基本一样,但是execAll方法为正则方法,而match方法为字符串方法,使用上略有不同
function execAll(str = "") {
// str是方法传递进来的参数,为需要进行匹配的字符串
// 先进行检验看是否具有全局属性g
if (this.global) {
// 把每一次捕获到的内容放进arr
let arr = [];
// 将计算一次的值赋给res
let res = this.exec(str);
// 判断res是否有值,有的话则将捕获的值(数组的第一个值)保存进arr,并再次执行exec方法。为null则无值,表示lastIndex再次为0
while (res) {
arr.push(res[0]);
res = this.exec(str);
}
return arr.length === 0 ? null : arr;
// r如果没有全局g,则直接返回执行一次的结果
} else {
return this.exec(str);
}
}
RegExp.prototype.execAll = execAll;
let reg2 = /\d+/g;
console.log(reg2.execAll("fu2020jun1999ling1920")); // ["2020", "1999", "1920"]
3.match()
//不加全局修饰符g的话,得到的结果等同于使用exec()方法不加g得到的结果
let reg2 = /(\d+)\w/
console.log('fu2020jun2021ling'.match(reg2))
//加全局修饰符g的话,得到的结果是所有大正则匹配的结果
let reg2 = /(\d+)\w/g
console.log(fu2020jun2021ling'.match(reg2))
// ["2020j", "2021l"]
自己创建一个可以获取所有正则和分组的函数
// 创建一个同时获取正则和分组的方法
function getBigOrSmall(str) {
if(this.global) {
let arr = []
let res = this.exec(str)
while(res) {
// 移出第一个索引的数据赋给big
let big = res.shift()
// 将剩余的数据给small
let small = [...res]
// 整理成对象push进arr数据
arr.push({big, small})
// 再次执行exec,改变lastIndex的值
res = this.exec(str)
}
// 判断数组长度并返回
return arr.length > 0 ? arr : null
}else {
// 没有全局修饰符g,直接返回执行一个的结果
return this.exec(str)
}
}
RegExp.prototype.getBigOrSmall = getBigOrSmall
4.replace()
//replace()可以实现字符串替换(一般跟随正则使用)
let str = 'fjl2020fjl2021fjl'
str = str.replace('fjl', 'fujunling')
console.log(str) //fujunling2020fjl2021fjl 默认只执行一次,全部替换需要多次执行
str = str.replace('fjl', 'fujunling').replace('fjl', 'fujunling')
console.log(str) //fujunling2020fujunling2021fujunling
//正则使用方法
let str = 'fjl2020fjl2021fjl'
let reg = /fjl/g
str = str.replace(reg, 'fujunling')\
console.log(str) //fujunling2020fujunling2021fujunling
//捕获作用
let str = 'fjl2020fjl2021fjl'
let reg = /fjl(\d+)fjl(\d+)fjl/g
str = str.replace(reg, '$1,$2')
console.log(str) //2020, 2021
//原理:
// 1. 首先将正则与字符串进行匹配捕获,匹配一次就执行一次
// 2.在匹配成功后会传递给第二个参数(一个函数)实参,实参为和exec捕获得到的信息一样(第一个参数为正则捕获的值,后面的参数为小分组捕获的值,然后是lastIndex,最后是原始字符串)
// 3.函数里返回的是啥就会被替换成啥
//例如:
let str = 'fjl2020fjl2021fjl'
let reg = /fjl(\d+)fjl(\d+)fjl/g
str = str.replace(reg, (...arg) => {
console.log(arg)
return arg
})
console.log(str ) //fjl2020fjl2021fjl,2020,2021,0,fjl2020fjl2021fjl (返回值会自动转换为字符串)
//0: "fjl2020fjl2021fjl"
//1: "2020"
//2: "2021"
//3: 0
//4: "fjl2020fjl2021fjl"
正向预查
?=辅助条件
查询出的内容后面必须跟着辅助条件
//正向匹配
//var reg = /pattern(?=模式)/;
//要求:匹配出来的hello字符串后边要跟着3个数字
var reg = /\w{3}(?=\d{3})/
let str = 'qqq$aaahui*cca222'
console.log(reg.exec(str))
//["cca", index: 11, input: "qqq$aaahui*cca222", groups: undefined]
负向预查
?!辅助条件
查询出的内容后面必须不跟着辅助条件
//var reg = /pattern(?=模式)/;
//要求:匹配出来的hello字符串后边要不跟着3个数字
var reg = /aaa(?!\d{3})/
let str = 'aaa333$aaahui*aaa222'
console.log(reg.exec(str))
//["aaa", index: 7, input: "aaa333$aaahui*aaa222", groups: undefined]