第二章 - 02: 前端 正则表达式 魔法 (上)
来源于:《JavaScript 忍者秘籍》
在我们的日常开发过程中其实会常常有遇到利用正则表达式来解决一些棘手的问题。比如获取当前链接的参数,匹配身份证、手机号、姓名、验证码等等等等。那么我们今天的 前端之路 系列就来聊一聊 正则表达式 !
一、创建!
既然是表达式,那么就一定是存在创建的过程的,如何创建?
创建一个正则表达式,有两种方式:
1、面向字面量:
const pattern = /test/
2、构造 RegExp 实例
const pattern = new RegExp('test')
// pattern -> /test/
两种方式的比较:
1、如果正则(规则)是已知的,则优先选择字面量语法。
2、如果是需要在运行的时候通过 动态构建的字符串来创建正则表达式,则需要通过构造器的方式
此外,还有三个标志可以和正则表达式进行关联:
1、 i: 让正则表达式不区分大小写[ignore case]
2、 g: 匹配模式中的所有实例 [global]
3、 m: 允许匹配多行,例如匹配文本元素 [multiline]
我们可能对上面讲到的 三点不太理解,那么我们用最简单的例子来解释一下。
### i: 让正则表达式不区分大小写[ignore case]
const reg = /test/i
const res1 = reg.test('testssss') // true
const res2 = reg.test('Testssss') // true
const reg2 = /test/
const res21 = reg2.test('testssss') // true
const res22 = reg2.test('Testaaaa') // false
### g: 匹配模式中的所有实例 [global]
const reg = /s/
let res1 = 'testssss'.match(reg)
// ["s", index: 2, input: "testssss", groups: undefined]
// 如果匹配到了第一个就
const reg2 = /s/g
let res2 = 'testssss'.match(reg2)
// ["s", "s", "s", "s", "s"]
### m: 允许匹配多行,例如匹配文本元素 [multiline]
<div>
<textarea id="text">
hahaha
</textarea>
<button id='btn'>
click
</button>
</div>
var str = ''
var reg1 = /$/g
var reg2 = /$/mg
var text = document.getElementById('text')
var btn = document.getElementById('btn')
btn.addEventListener('click', function(e) {
// str = text.value
str = '1\n2\n3\n4\n5'
var s1 = reg1.test(str) // 空
var s2 = reg2.test(str) // 2345
console.log(RegExp.rightContext)
})
其实到了这一步,对于 m 的用法还不是特别的清晰,后面,我们遇到了真实的问题,会再次回来解决这个问题的。
二、术语与操作符
2.1 精确匹配
如果一个字符不是特殊字符或操作符,则表示该字符必须在表达式中出现、例如/test/中有四个字符,它们表示这四个字符必须按顺序一个接着一个的出现,才能匹配得到。
2.2 匹配一类字符
2.2.1
匹配一个有限字符集中的某一个字符时,可以用 [ ]eg:
var reg = /[abc]/
var str1 = 'a'
var str2 = 'ab'
var str3 = 'ab'
var str4 = 'adc'
var str5 = 'dd'
var res1 = reg.test(str1) // true
var res2 = reg.test(str2) // true
var res3 = reg.test(str3) // true
var res4 = reg.test(str4) // true
var res5 = reg.test(str5) // false
// 总结下来就是 [] 可以用来匹配任意括号内的内容。
// /[abc]/ 包含了 [a] [b] [c] [ab] [ac] [bc] [abc]
// 只要字符串中包含了 上述表达式中的任何一个 都算是满足需求。
2.2.2
匹配一个有限字符集之外的字符,可以用 [^]eg:
var reg = /[^abc]/
var str1 = 'a'
var str2 = 'ab'
var str3 = 'ab'
var str4 = 'adc'
var str5 = 'dd'
var res1 = reg.test(str1) // false
var res2 = reg.test(str2) // false
var res3 = reg.test(str3) // false
var res4 = reg.test(str4) // true
var res5 = reg.test(str5) // true
// 总结下来就是 [^] 可以用来匹配任意括号内以外的内容
// 只要字符串中包含了 上述表达式中的任何一个以外的字符 都算是满足需求。
2.2.3
制定一个范围,可以使用 [ - ]
eg:
var reg = /[a-z]/
var str = 's'
var res = reg.test(str)
console.log(res) // true
例如[a-z]表示的是a到z之间的所有字符(包括a,z,按字典顺序)
2.3 转义
当要匹配特殊字符的时候,需要对其进行转义,例如$,^,[等,需要使用反斜杠
eg:
var reg1 = /\[/
var reg2 = /[/
var str = '['
var res1 = reg1.test(str) // true
var res2 = reg2.test(str) // 报错
2.4 匹配开始与结束
2.4.1
符号^如果作为正则表达式的第一个字符,则表示要从字符串的开头开始匹配2.4.2
符号$作为正则表达式的最后一个字符,表示该模式必须出现在字符串的结尾eg:
var reg1 = /^./g
var reg2 = /[a-d]/g
var reg3 = /.$/g
var str = 'esdasdasdasewcfefhdasjkld'
var res1 = str.match(reg1)
var res2 = str.match(reg2)
var res3 = str.match(reg3)
console.log(res1) // e 字符串的第一个
console.log(res2) // ['d','a',...,'d']
console.log(res3) // d 字符串的最后一个
2.5 重复出现
当匹配连续的任意数量 相同字符时,可以采用下面的方式
2.5.1 ?
: 可以定义该字符是可选的,即可以出现一次或者不出现
eg:
var reg = /t?est/
var str1 = 'trrrrtttttttest'
var str2 = 'trrrrest'
var str3 = 'trrrrrst'
var res1 = reg.test(str1)
var res2 = reg.test(str2)
var res3 = reg.test(str3)
console.log(res1) // true
console.log(res2) // true
console.log(res3) // false
如何理解呢? 问号表示疑惑? 表示2种可能,可能有也可能没有
2.5.2 +
: 一个字符至少出现一次
eg:
var reg = /t+est/g
var str = 'testtttttest'
var res = str.match(reg)
console.log(res) // ["test", "tttttest"]
如何理解呢? 加号表示相加。那么相加的话,就是至少出现一次
2.5.3 *
: 一个字符不出现或者出现多次
eg:
var reg = /t*est/g
var str1 = 'testest'
var str2 = 'testtttest'
var res1 = str1.match(reg)
var res2 = str2.match(reg)
console.log(res1) // ["test", "est"]
console.log(res2) // ["test", "tttest"]
如何理解呢? 星号表示的 比价随意 , 可以出现 也可以不出现。 综合了 加号 和 问号。
2.5.4 {n}
: 表示一个字符 重复出现 n 次
eg:
var reg = /t{4}/g
var str1 = 'testest'
var str2 = 'testtttest'
var res1 = str1.match(reg)
var res2 = str2.match(reg)
console.log(res1) // null
console.log(res2) // ["tttt"]
如何理解呢? 这个 n 其实相对来说还是比较好理解的。 n次~
2.5.5 {n,m}
: 表示一个字符 重复出现 n 至 m 次
eg:
var reg = /t{2,5}/g
var str1 = 'testest'
var str2 = 'testtttest'
var str3 = 'testtest'
var res1 = str1.match(reg)
var res2 = str2.match(reg)
var res3 = str3.match(reg)
console.log(res1) // null
console.log(res2) // ["tttt"]
console.log(res3) // ["tt"]
2.5.6 {n,}
: 表示一个字符 至少 重复出现 n 次
eg:
var reg = /t{1,}/g
var str1 = 'testest'
var str2 = 'testtttest'
var str3 = 'testtest'
var str4 = 'esaesa'
var res1 = str1.match(reg)
var res2 = str2.match(reg)
var res3 = str3.match(reg)
var res4 = str4.match(reg)
console.log(res1) // ["t", "t", "t"]
console.log(res2) // ["t", "tttt", "t"]
console.log(res3) // ["t", "tt", "t"]
console.log(res4) // null
Tips
: 在匹配的时候,还有一点要注意的是:贪婪和非贪婪。在默认情况下,它们是贪婪的,即会匹配所有的字符组合,在操作符后面加一个?,可以让该表达式成为非贪婪的,进行最小限度的匹配
eg:
var reg1 = /a+/g
var reg2 = /a+?/g
var str = 'aaa'
var res1 = str.match(reg1) // ['aaa']
var res2 = str.match(reg2) // ["a", "a", "a"]
这里提到了一个 正则表达式中一个比较重要的 概念就是
贪婪
和非贪婪
贪婪匹配
就是: 正则表达式一般趋向于最大长度
的匹配(默认为贪婪匹配)。非贪婪匹配
就是: 正则表达式匹配到就好
了,不再继续往后走。
在操作符后面加一个?
就可以将 贪婪变成非贪婪。
GitHub 地址:(欢迎 star 、欢迎推荐 : )