乐趣区

面试必背系列正则上

正则

引言

正则是一个前端必须掌握的知识。但是由于用的少,忘了记,记了忘,导致面试经常坐蜡。这里上篇先介绍正则的规则,下篇结合一些具体题目,带大家重新学习巩固一下正则,争取面试给自己加分。

简介

介绍:用来处理字符串的一个规则

正则:判断一个字符串是否符合我们的规则 -> reg.test(str)
捕获:把字符串中符合我们规矩的子字符捕获到 ->reg.exec(str)

规则

生成正则的两种方式

实例创建和使用字面量,但是要注意 使用实例创建正式是可以使用变量进行拼接的

正则表达式由两种基本字符类型组成,原义文本字符和元字符

元字符:在正则表达式中具有特殊意义的字符,原义字符变元字符加 ”

元字符分类

边界类

^ 开头 $ 结尾 b 单词边界 B 非单词边界

/\bengineer$/.test('I am an engineer') //true
量词类

*:零次到多次
+:1 次到多次
?: 0 次或者 1 次
{n} 出现 n 次
{n,m} 出现 n 次到 m 次

   let reg = /1\d{10}$/ // 验证手机号,第一位是 1 
范围类

[a-z] a- z 之间的任何一个字符
[a-zA-Z] a- z 以及 A - Z 之间的任何一个字符

'a1b2C3C4'.replace(/[a-z]/g,'Q') //"Q1Q2C3C4"
字符类
x|y:x 或 y 中的一个
[xyz]: x 或者 y 或者 z 中的一个
[^a-z] 除了 a - z 以外的任何一个字符
[^xyz] 除了 xyz 以外的任何一个字符
预定义类
// .  除了回车和换行的所有字符 [^\r\n]
// \d 数字 [0-9]
//  \s  空白字符 [\t\n\x0B\f\r]
// \w 单词 字符[A-Za-z0-9_]  // 注意,. 的范围要比 \W 范围大,因为它还包括制表符之类的 ` 注意只是一个字符而不是一个单词 `
'hello'.replace(/\w{2}$/g,'x')  //helx

修饰符以及 正则对象属性

修饰符:

i 忽略大小写
g 全局匹配
m 多行匹配
注意这里设置了,在正则对象里的相应属性会改变

var a = /\d/g
a.global  //true
var b = /\d/
b.global  //false

正则对象属性:

global ignore case multiline lastIndex sourse
注意,lastindex 在全局匹配里面会匹配一次改变一个,超出匹配范围会被清零

var reg1 = /\w/
var reg2 = /\w/g
reg1.test('a') //true //reg1.lastIndex //0
reg1.test('a') //true //reg1.lastIndex //0
reg1.test('a') //true //reg1.lastIndex //0
reg2.test('a') //true //reg2.lastIndex //1
reg2.test('a') //false //reg2.lastIndex //0
reg2.test('a') //true //reg2.lastIndex //1
reg2.test('a') //false //reg2.lastIndex //0

贪婪模式和非贪婪模式

正则默认是贪婪模式,会按尽可能多的匹配,在量词后面加?可以取消贪婪性

123456.replace(/\d{3,6}/g,'x') // 由于有贪婪性,按 6 次匹配, 结果为 'x'
'123456'.replace(/\d{3,6}?/g,'x') // 此时没有贪婪性,但是有全局匹配,结果为 'xx'
'123456'.replace(/\d{3,6}?/g,'x') // 此时没有贪婪性,局部匹配,结果为 'x456'

分组以及或

或 |,左边的单词(分组)或者右边的单词(分组)出现都可以
分组的目的是为了更好的捕获,增加控制力 分组可以用 num 代表
注意或 | 的优先级是最低的,比字符串串接的优先级还要小,所以有 /Bayron|casper/ 是匹配两个单词而不是 n 或者 c 的情况

bary{3}  // y 重复 3 次
(bary){3} // 单词重复 3 次
Bayron|casper // 两个单词的或   
Bayr(on|ca)sper // 中间两个字母随便出现哪个都行, 注意同时出现两个是不匹配的
'Bayroncasper'.replace(/Bayr(on|ca)sper/g,'x') //"Bayroncasper"
'Bayrcasper'.replace(/Bayr(on|ca)sper/g,'x')  //"x"

前瞻和后顾

正则匹配的方向是从左向右,所以向右是前瞻,向左是后顾,断言可以理解为规则,但是不参与匹配
(正向)前瞻就是在正则表达式匹配到规则的时候,向前检查是否符合断言
(正向)后顾就是在正则表达式匹配到规则的时候,向后检查是否符合断言
(负向)… 就是正则表达式匹配到规则的时候,向(前)后检查是否不符合断言

'Windows2000'.replace(/Windows(?=2000)/g,'x')  //"x2000" 正向前瞻 ?=
'Windows2000'.replace(/Windows(?!2000)/g,'x')  //"windows2000" 负向前瞻 ?!
'I has Windows2000'.replace(/(?<=I has)Windows/g,'x')  //"I has x2000" 正向后顾 ?<=
'I has Windows2000'.replace(/(?<!He has)Windows/g,'x')  //"I has x2000" 负向后顾 ?<!

方法

正则的方法

正则的方法只有两个,test 和 exec

exec

一个在字符串中执行查找匹配的 RegExp 方法,它返回一个数组(未匹配到则返回 null)。与字符串的 match 对应 数组【匹配值,分组,index,input,】
这里注意,exec 一次只匹配一个,匹配不到就会 null。只有给修饰符 g 才能往下继续匹配(使用 while)

var myRe = new RegExp("d(b+)d", "g");
var myArray = myRe.exec("cdbbdbsbz");
console.log(myArray)
//["dbbd", "bb", index: 1, input: "cdbbdbsbz", groups: undefined]
---------------------------------------------------------------------
var regex1 = RegExp('foo*','g');
var str1 = 'table football, foosball';
var array1;

while ((array1 = regex1.exec(str1)) !== null) {console.log(`Found ${array1[0]}. Next starts at ${regex1.lastIndex}.`);
  // expected output: "Found foo. Next starts at 9."
  // expected output: "Found foo. Next starts at 19."
}
test

一个在字符串中测试是否匹配的 RegExp 方法,它返回 true 或 false。与字符串的 search 对应

字符串的方法
search,match

类似 test,exec 但是全局调用 match 相对 exec 功能弱了一些,返回的数组元素没有 index 或者 input 了

split

非常有用的一个方法,用来按规则分解字符串形成数组

'a1b2c3d4'.split(/\d/g)
// ['a','b','c','d']
replace

非常非常有用的一个方法,全局匹配下由于能自动不断匹配,非常方便。
注意如果参数是字符串会隐式转换为

'a1b1'.replace('1','x') // axb1   为什么会只替换一次呢,因为这里会给你隐式的转换为正则表达式
'a1b1'.replace(/1/g,'x') // axbx
'a1b1'.replace(/\d/g,function(match){ // 匹配字符串,分组(没有则没有该参数),index,原字符
    return ~~match + 1
}) // a2b2
退出移动版