今天我们来讲一下正则表达式的基本使用
正则表达式的修饰符
-
i 执行对大小写不敏感的匹配
let a = 'hEllo World' let reg = /hello/i console.log(reg.test(a)) // true let str = 'hello' let reg1 = /Hello/i console.log(reg1.test(str)) // true let str1 = 'hello' let reg2 = /Hello/ console.log(reg2.test(str1)) // false
上面的第一个例子字符串a带有大写英文,而我们的匹配方式则为全部小写,我们会得到true,第二个例子str字符串全部为小写,而匹配方式则为大小写混合也是得到true,第三个则是不使用修饰符i的,得到为false,所以i是对大小写不敏感的
-
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)
let a = 'hello hello hello hello' let reg = /hello/g console.log(a.replace(reg, '*')) // * * * * let a1 = 'hello Hello hello Hello' let reg1 = /Hello/g console.log(a1.replace(reg1, '*')) // hello * hello * let a2 = 'hello Hello hello Hello' let reg2 = /Hello/gi console.log(a2.replace(reg2, '*')) let a3 = 'hello _Hello hello Hello' let reg3 = /Hello/gi console.log(a3.replace(reg3, '*'))* _* * *
对于g全局的匹配,我对于它的理解就是能找到的都可以,只要符合的行,看上面的四个例子,最主要是看最后一个一个例子不管是不是一体只要符合你的规则就可以
-
m 多行匹配
let a = 'hello\n hello hello hello' let reg = /hello/m console.log(a.replace(reg, '*')) // * hello hello hello let a1 = 'hello Hello\n hello Hello' let reg1 = /Hello/m console.log(a1.replace(reg1, '*')) // hello * hello hello let a1 = 'hello hello\n hello Hello' let reg1 = /Hello/m console.log(a1.replace(reg1, '*')) //hello hello hello *
通过上面的两个例子,我们已经知道m修饰符也算是查找全局的修饰符但是它匹配到一个就不会再进行匹配了
-
es6新增修饰y,又叫做粘连修饰符,和g修饰符类似也是全局匹配
let str = "anta" let y = /a/y console.log(str.replace(y, "&")) // &nta console.log(str.replace(y, "&")) // anta let str = "aanta" let y = /a/y console.log(str.replace(y, "&")) //&anta console.log(str.replace(y, "&")) //a&nta console.log(str.replace(y, "&")) //aanta
上面第一个例子使用了y修饰符,第一次执行我们匹配到了a替换成功,第二次的时候没有值被匹配到,这是因为y修饰符匹配到一次后,会接着当前匹配到位置的下一个位置开始,所以在第一次替换的时候位置为0,第二次匹配的时候位置则变为了1,y修饰符是具有位置属性的位置匹配,下面我们就来看一下
let str = "aanta" let y = /a/y y.lastIndex = 4 console.log(str.replace(y, "&")) // aant& y.lastIndex = 1 console.log(str.replace(y, "&")) // a&nta
上面的两个例子则是使用了位置,我们可以看到使用位置之后,会打乱y修饰符原有的粘连方式,会直接按照我们规定的位置1匹配
let str = "aanta" let y = /a/gy console.log(str.replace(y, "&")) // &&nta
上面的例子是g和y修饰符配合使用,会得到我们意想不到的结果,因为它会按照粘连规则检验
-
RegExp.prototype.sticky 属性检验是否设置了y修饰符
let y1 = /a/y console.log(y1.sticky) // true let y = /a/gy console.log(y.sticky) // true
-
RegExp.prototype.flags 属性返回设置的修饰符
let y1 = /^a/y console.log(y1.flags) // y let y = /a/gy console.log(y.flags) // gy
-
es6 新增修饰符s 符号.匹配所有字符
let str = "aa\nnta" let reg = /a.n/s console.log(reg.test(str),reg.dotAll) // true true let str = "aa\nnta" let reg = /a.n/ console.log(reg.test(str),reg.dotAll) // false false
修饰符s匹配换行符n,我们会得到true,如果不用s修饰符的话会匹配不到的,上面的例子中都有检测是否存在dotAll模式中,说白了主要就是看你有没有修饰符s
正则表达式模式
-
[] 匹配中括号内规则的字符
let str = "hello world" let reg = /[a-z]/ console.log(reg.test(str)) // true let str = "hello world" let reg = /[a-h]/g console.log(str.replace(reg, '*')) // **llo worl* let str = "he1l3 wo4ld" let reg = /[0-9]/g console.log(str.replace(reg, '#')) // he#l# wo#ld
上面只是简单的两个例子只是简单的测试下是否可以匹配到中括号内的相关规则字符串
-
| 匹配多个规则相当于||或
let str = "he1l3 wo4ld" let reg = /[0-9|a-d]/g console.log(str.replace(reg, '#')) // he#l# wo#l# let str = "he1l3 wo4ldc@" let reg = /[0-9|a-d|c.]/sg console.log(str.replace(reg, '#')) // he#l# wo#l##@
上面第一个例子使用了g修饰符全局匹配0-9内的数字和a-d的字母替换,第二个例子使用了s和g的修饰符
-
正则表达式元字符
名字 使用描述 /d 匹配数字 D 非数字字符 /s 查找空白字符 S 非空白字符 /b 匹配单词边界 n 匹配换行符 w 单词字符 W 非单词字符 /+ 出现一到多次 $ 匹配结尾 \ 转义 ^ 匹配头部出现的 t 匹配制表符 0 查找null 我们按照顺序写几个简单的例子
匹配数字,只要是数字都能匹配到 let str = "hello 1235" let reg = /\d/g console.log(str.replace(reg, '*')) // hello **** 查找空白字符 let str = "hello 1235" let reg = /\s/g console.log(str.replace(reg, '*')) // hello*1235 匹配单词边界 let str = "hello 1235" let reg = /\b/g console.log(str.replace(reg, '*')) // *hello* *1235* 匹配换行符 let str = "hello\n123\n5" let reg = /\n/g console.log(str.replace(reg, '*')) // hello*123*5 /w匹配[a-zA-Z0-9_] let str = "Abv12_$" let reg = /\w/g console.log(str.replace(reg, '*')) // ******
匹配结尾的$
let str = "Abv12"
let reg = /v$/g
console.log(reg.exec(str)) // null
let str = "Abv12v"
let reg = /v$/g
console.log(reg.exec(str)) // ["v", index: 5, input: "Abv12v", groups: undefined]
^匹配开头的
let str = "Abv12v"
let reg = /^v/g
console.log(reg.exec(str)) // null
let str = "vAbv12v"
let reg = /v$/g
console.log(reg.exec(str)) //["v", index: 0, input: "vAbv12v", groups: undefined]
^和$配合使用
let str1 = "abcd 1"
let reg1 = /^[a-z]+\s+\d+$/i
console.log(str1.replace(reg1, '*')) // *
匹配abcd 1,需要对应的规则分别是abcd ^[a-z] 空格s d数字$
{} 和 () 和 ?的使用
{n} 匹配n个
{n,} 最少n个
{n, n} 最少匹配n个,最大匹配n个
()捕获性分组使用
let str = '2018-03-02'
let reg = /^(\d{4})-(\d{2})-(\d{2})$/
console.log(str.replace(reg, "$1/$2/$3")) // 2018/03/02
上面的例子使用了()和{}配合使用,分成了三个组,第一个组匹配四个数字,第二个和第三个匹配两位数字,然后利用了^开始匹配的四位数字开始和$匹配两位数字结束,将-替换/
()非捕获性使用 非捕获性分组通过将子表达式放在"?:"符号后,我理解的非捕获性分组就是()有根没有都一样
let str = '2018-03-02'
let reg = /^(?:\d{4})-(?:\d{2})-(?:\d{2})$/
console.log(str.replace(reg, "$1/$2/$3")) // $1/$2/$3
上面的例子就是一个非捕获性的例子,在子表达式前面加上?:就可以解除小括号的分组模式所以匹配不到
贪婪模式与非贪婪模式
说到贪婪模式和非贪婪模式,首先我要介绍一下量词,因为非贪婪模式要用在量词后面
n{X}匹配包含X个n的序列的字符串
n{X,Y}匹配包含X至Y个n的序列的字符串
n{X,}匹配至少包含 X 个 n 的序列的字符串
n*匹配任何包含零个或多个 n 的字符串
n?匹配任何包含零个或一个 n 的字符串
n+匹配任何至少包含一个 n 的字符串
贪婪模式就是尽可能多的匹配
let str = 'abcdefghijk123'
let reg = /\w{1,4}/
console.log(str.replace(reg, "*")) // *efghijk123
上面的例子则为贪婪模式它会匹配到最大的那个位数
let str = 'abcdefghijk123'
let reg = /\w{1,4}?/
console.log(str.replace(reg, "*")) // *bcdefghijk123
上面的例子则为非贪婪模式,只会去匹配最少的位数
先行断言和先行否定断言(匹配到前面的)
先行断言?=
let str = 'abcdefghijk123asd456'
let reg = /\w+(?=123)/g
console.log(str.match(reg)) // ["abcdefghijk"]
上面的例子为先行断言的例子reg规则必须是后面带有123的匹配到
先行否定断言?!
let str = 'bbb123 bbbbb456'
let reg = /b{3,}(?!123)/g
console.log(str.match(reg)) // ["bbbbb"]
后行断言和后行否定断言(匹配到后面的)
后行断言查找匹配表达式匹配到后面的
let str = 'abcdefghijk123asd456'
let reg = /(?<=123)[a-z]/g
console.log(str.match(reg)) // ["a"]
后行否定断言,匹配不属于123的,后面的[a-z]的字符
let str = 'abcdefghijk123asd'
let reg = /(?<!123)[a-z]+/g
console.log(str.match(reg)) // ["abcdefghijk", "sd"]
我感觉先行断言像后行否定断言,先行否定断言像后行断言
RegExp 构造函数对象
new RegExp(pattern,modifiers)
pattern 则为表达式
modifiers 则为修饰符
let reg1 = new RegExp('[a-z]','g')
console.log(reg1) // /[a-z]/g
上面的例子我们会得到这个结果是因为RegExp对象会将第二个参数修饰符与第一个参数表达式进行合并
let reg1 = new RegExp(/[a-z]/,'g')
console.log(reg1) // /[a-z]/g
上面这个例子我们也会得到我们想要匹配全局的一个表达式,但是在es5中如果这样写就会出现报错
let reg1 = new RegExp(/[a-z]/,'g')
console.log(reg1.flags) // g
let reg1 = new RegExp(/[a-z]/,'i')
console.log(reg1.flags) // i
我们还可以检测表达式是否使用了修饰符,并且可以知道使用了什么修饰符
正则表达式的方法
- RegExp 对象方法
compile | 编译正则表达式 |
---|
let str = '123.jpg456.png'
let reg = /[123]/g
console.log(str.replace(reg, 'x')) // xxx.jpg456.png
reg.compile(/[456]/g)
console.log(str.replace(reg, 'x')) // 123.jpgxxx.png
let str = '123.jpg456.png'
let reg = /[123]/g
console.log(str.replace(reg, 'xx')) // xxxxxx.jpg456.png
上面的第一个例子使用了表达式方法compile它会使表达式重新编译或是修改,所以第一次匹配的是123,第二次则是456,是因为改变了匹配机制,第二个例子使用用到了替换的方法并且会发现你替换的参数多的话会修改字符串的长度
exec | 根据正则表达试查找对应的字符和位置 |
---|
let str = '2018-02-13'
let reg = /-\d{1,2}/g
console.log(reg.exec(str)) // ["-02", index: 4, input: "2018-02-13", groups: undefined]
上面的例子是查找带有-数字不超过2位,返回的是数组,并且把匹配到的第一个在最前面的位置
test | 根据正则表达试是否匹配到布尔值 |
---|
- 正则表达式的 String 对象的方法
search | 检索与正则表达式相匹配的值 |
---|
let str = '2018-02-13'
let reg = /-\d{1,2}/g
console.log(str.search(reg)) // 4
它会返回你表达式匹配到第一个字符的位置返回,它会对大小写敏感如果查找不到会返回-1,无视g
match | 找到一个或多个正则表达式的匹配 |
---|
let str = 'this is 1 or 2'
let reg = /\d/g
console.log(str.match(reg)) // [1,2]
它会找出所有与你表达式匹配到的字符放入数组中
replace | 替换 |
---|
replace替换我们上面已经使用过很多次了,大家可以仔细阅读看
matchAll | 匹配所有,表达式不用使用全局修饰符 |
---|
es6的正在提案的一个方法,它可以摒弃全局的修饰符,达到全局的匹配,它会返回一个遍历器,然后可以通过结构赋值拿到想要的结果
上面我们学习了那么多,那我们就运用所学写一些表达式
/^1[3|4|5|7|8][0-9]{9}$/ 匹配手机号开头必须有1,34578其中的一个,结尾必须9位数而且是0-9的数字
/^0315(-?)[0-9]{7}$/ 判断电话区号和-可有可无
/^[0-9]{4}(-?)[0-9]{7}$/ 匹配1-9的数字必须是四位,可有可无-,匹配7位数字
都是几个比较简单的表达式,还需多学习,多练习才能写出更广泛更精准的表达式
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。