持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第14天,点击查看活动详情
前言
经常听到同事说正则是一大利器,后端同事更是对正则使用的滚瓜烂熟;然而真正等到需求来了之后发现很多正则还是需要前端来写的,但是自己对这一块不太熟悉,于是只能向老大求助;从此之后老大便喜欢在面试中去出这种正则题目了,所以我们还能不学正则吗?
匹配字母、数字
字母和数字是字符串的主要组成部分因此这一块是正则表达式最重要的一块
匹配字母、数字 | 含义 | 示例 |
---|---|---|
. | 换行符之外的字符 | 例如用/./g来匹配ABC,会有三个结果:'A','B','C' |
\d | 数字 | 用/\d/g匹配NB123ABC,获得三个结果1,2,3,等同于[0-9] |
\D | 数字以外字符 | |
\s | 空白符 | /\s/.exec('')[' ', index: 4, input: '', groups: undefined] |
\S | 空白符以外字符 | |
\w | 字母,数字,下划线,汉字 | /\w/.exec("m123字母_")['m', index: 0, input: 'm123字母_', groups: undefined] |
\W | 除了“字母,数字,下划线,汉字”以外的字符 | /\W/.exec('<>')匹配到< |
\r | 回车 | |
\n | 换行符 |
分组
组和范围 | 含义 | 示例 | |
---|---|---|---|
x | y | 匹配x或者y | |
[xyz] | 匹配x或者y或者z | ||
(x) | 以x为一组 | ||
\n | n为数字,重复匹配前面的结果 |
量词
量词 | 含义 | 示例 |
---|---|---|
+ | 匹配一次或多次 | /\d+/.exec("ABC123op12")会匹配到123,连续的数字 |
? | 0或1次 | /[A-Z]?/.exec('ABC123op12')匹配到了A |
* | 0次或者多次 | /[A-Z]*/.exec('ABC123op12')匹配到ABC |
{n} | 匹配n次 | /[A-Z]{3}/.exec('ABC123op12')匹配到ABC |
{n,} | 匹配n或更多次 | |
{n,m} | 匹配n到m次 |
断言(匹配位置的)
断言(匹配位置的) | 含义 | 示例 |
---|---|---|
?=exp | 匹配字符后面必须是exp | |
?<=exp | 匹配字符前面必须是exp | |
?<!exp | 前面不是exp | |
?=exp | ||
?!exp | ||
以...开头 | /^./.exec('')['<', index: 0, input: '', groups: undefined] | |
[^x] | 不以x开头的元素 | |
$ | 以...结尾 | /.$/.exec('')['>', index: 23, input: '', groups: undefined] |
\b | 单词开始或者结尾 | /\b/.exec("ABC")可以得到单词边界 |
\B | 单词之间的的边界 | '1234'.replace(/\B/,'R')会得到1R234,匹配的是1和2之间的边界 |
真题
-
匹配连续3个或3个以上的相同数字
分析:这里要用到分组中的\n匹配相同的模式串,还要用到量词和分组;先分组匹配数字然后以相同模式串匹配2次以上
/(\d)\1{2,}/g
-
匹配html标签
分析:匹配html标签在前端中应用十分广泛:例如vue源码中就有对标签的匹配,与富文本相关的敏感词以及一些标签的过滤这都需要用到匹配标签的正则;标签分为头、尾、内容,头则由一组尖括号组成,里面有空格以及属性等,例如:
<div class="abc">12</div>
,为了不匹配到后面的闭合标签,我们“<”后面需要紧跟一个字母,所以这样写<[a-z].*?>
匹配头部标签,然后中间的内容则用.*?
匹配,最后组合一下:<[a-z].*?>.*?<\/[a-z].*?>
,比如我们要匹配这个div中的class替换它就用这个正则表达式:/(?<=\<div.*class\=\")(.*)(?=\")/
-
提取连接地址:
IT面试题博客中包含很多<a href="http://hi.baidu.com/mianshiti/blog/category/微软面试题">微软面试题</a>
分析:链接前面后面都是文字,所以还是用断言,和上面差不多:
/(?<=")(.+)(?=")/
-
敏感词过滤
分析:只需要把敏感的字或者词组用|连接起来即可
-
对人口数字的格式化处理,三位数字用一个','(逗号)隔开
分析:这道题目一看就是需要匹配边界,然后替换为,即可;但是我们需要借助限定符来确定这个边界的位置;这个边界的后面应该是三个数字,难点在于最后面应该是结尾所以应该没有数字所以应该使用
(?!\d)
来限定结尾,最后答案是:/\B(?=(\d{3})+(?!\d))/g
性能
正则的匹配属于贪婪匹配,它会尽量多地匹配;在匹配的过程中会进行回溯,例如'abclbkb'要匹配bcb,先设置index=0,将a与b进行匹配发现匹配失败,index=1,匹配成功,再匹配c又匹配成功,最后b匹配失败,将会回溯到c,从c开始又重新进行匹配
因此我们写的正则表达式匹配次数影响到它的性能,我们需要尽量写出匹配次数较少的正则表达式
总结
学完了正则表达式的基础,同时根据面试真题进行了实战,最后我们了解了一下正则表达式的性能问题,相信以后面对字符串替换类的问题我们不再纠结