Web前端最新正则表达式从入门到入坑_正则匹配第一个符合的,附面试答案

ES6

  • 列举常用的ES6特性:

  • 箭头函数需要注意哪些地方?

  • let、const、var

  • 拓展:var方式定义的变量有什么样的bug?

  • Set数据结构

  • 拓展:数组去重的方法

  • 箭头函数this的指向。

  • 手写ES6 class继承。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

微信小程序

  • 简单描述一下微信小程序的相关文件类型?

  • 你是怎么封装微信小程序的数据请求?

  • 有哪些参数传值的方法?

  • 你使用过哪些方法,来提高微信小程序的应用速度?

  • 小程序和原生App哪个好?

  • 简述微信小程序原理?

  • 分析微信小程序的优劣势

  • 怎么解决小程序的异步请求问题?

元字符描述
\将下一个字符标记为一个特殊字符、或一个原义字符、或一个 向后引用、或一个八进制转义符。
^匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。
$匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。
\b匹配一个单词边界,也就是指单词和空格间的位置。
\B匹配非单词边界。
\d匹配一个数字字符。等价于 [0-9]。
\D匹配一个非数字字符。等价于 [^0-9]。
\f匹配一个换页符。
\n匹配一个换行符。
\r匹配一个回车符。
\s匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\w匹配字母、数字、下划线。等价于’[A-Za-z0-9_]'。
\W匹配非字母、数字、下划线。等价于 ‘[^A-Za-z0-9_]’。

不运用起来的知识都不是自己的知识,所以看完总得写点例子建立思维记忆。
比如:
1、匹配有hello开头的字符串:

let str = "hello world";
// 方法一
let reg = /^hello/;
reg.test(str); //true
// 方法二
let reg2 = /\bhello/;
reg2.test(str); //true

这么一看\b和^好像功能差不多,其实不然,我们看下一个例子:

let str = "say hello";
let reg = /^hello/;
reg.test(str); //false
let reg2 = /\bhello/;
reg2.test(str); //true

可以看出\b并不是匹配开头,它匹配的是单词边界。

2、匹配1开头的11位数字的手机号码:

let phone = "13388882983";
let reg = /^1\d\d\d\d\d\d\d\d\d\d$/

3、匹配8的数字、字母和下划线组成的密码:

let password = "A_1234_b"
let reg = /^\w\w\w\w\w\w\w\w$/

2、重复限定符

匹配每一个数字都得写一个/d,代码怎么可以这么冗余,我们追求的是优雅,那该怎么写呢?我们先看下面的限定符。

语法描述
*匹配前面的子表达式零次或多次。* 等价于{0,}。
+匹配前面的子表达式一次或多次。+ 等价于 {1,}。
?匹配前面的子表达式零次或一次。? 等价于 {0,1}。
{n}n 是一个非负整数。匹配确定的 n 次。
{n,}n 是一个非负整数。至少匹配n 次。
{n,m}m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。配n 次。

看完我们对刚刚的正则进行一点点优雅的改造。
1、匹配8的数字、字母和下划线组成的密码:

let password = "A_1234_b"
let reg = /^\w{8}$/

但是产品觉得限制8位太不灵活了,它要8-15位,好,满足它:

let password = "A_1234_b"
let reg = /^\w{8,15}$/

2、匹配以a开头的,中间带有一个或多个b,0个或多个c结尾的字符串:

let reg = /^ab+c*$/;
let str = "abbc";
reg.test(str);  //true
let str2 = "abb";
reg.test(str2); //true
let str3 = "acc";
reg.test(str3); //false

3、区间 []

产品想法越来越多,密码希望只能给用户设置由大小写字母和数字组成的8-15位密码,摸了摸刀柄,决定继续满足它。

let reg = /^[A-Za-z0-9]{8,15}$/;
let password = "A123456789b";
reg.test(password);  //true
let password2 = "A_1234_b";
reg.test(password2);  //false

4、条件或

产品给你点了个赞然后提出了手机号码验证要优化的想法,调查发现VIP客户的手机只有13、156、176、186开头的11位数,要我们进行精确一点匹配。看了一眼它更长的刀,默默的写下下面的正则:

let reg = /^(13\d|156|176|186)\d{8}$/

产品表示很满意,结束了它的基本需求。

5、修饰符

标记也称为修饰符,正则表达式的标记用于指定额外的匹配策略。
标记不写在正则表达式里,标记位于表达式之外,格式如下:

/pattern/flags

修饰符含义描述
iignore - 不区分大小写将匹配设置为不区分大小写,搜索时不区分大小写: A 和 a 没有区别。
gglobal - 全局匹配查找所有的匹配项。
mmultiline - 多行匹配使边界字符 ^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾。
s特殊字符圆点 . 中包含换行符 \n默认情况下的圆点 . 是匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后, . 中包含换行符 \n。
let str = 'The fat cat eat the fish on the dish.'
let reg = /the/
str.match(reg); //["the",index:16]

通常正则匹配到第一个就会自动结束,因此我们只能匹配到the fish中的ths就结束了,如果我们希望把后面的"the"也匹配出来呢?这时候我们就要加一个全局匹配修饰符了。

let str = 'The fat cat eat the fish on the dish.'
let reg = /the/g
str.match(reg); //["the","the"]

要是希望把开头大写的"The"也一起匹配出来呢?这时候我们需要再加多一个全局匹配修饰符i。

let str = 'The fat cat eat the fish on the dish.'
let reg = /the/gi
str.match(reg); //["The","the","the"]

一般我们使用^或$只会匹配文章的开头和结尾。

let str = 'The fat cat eat the fish on the dish.\nThe cat is beautiful.'
let reg = /^The/g
str.match(reg); //["The"]

但是如果我们需要匹配各个段落的开头呢?

let str = 'The fat cat eat the fish on the dish.\nThe cat is beautiful.'
let reg = /^The/gm
str.match(reg); //["The","The"]

默认情况下的圆点 . 是匹配除换行符 \n 之外的任何字符。如:

let str = 'The fat cat eat the fish on the dish.\nThe cat is beautiful.'
let reg = /.+/
str.match(reg); //["The fat cat eat the fish on the dish.",...]

我们发现遇到\n的时候会切换了匹配,如果我们想继续完全匹配下去,需要加上修饰符s。

let str = 'The fat cat eat the fish on the dish.\nThe cat is beautiful.'
let reg = /.+/s
str.match(reg); //['The fat cat eat the fish on the dish.\nThe cat is beautiful.',...]

6、运算符优先级

正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似。
相同优先级的从左到右进行运算,不同优先级的运算先高后低。下表从最高到最低说明了各种正则表达式运算符的优先级顺序:

运算符描述
\转义符
(), (?: ), (?=), []圆括号和方括号
*, +, ?, {n}, {n,}, {n,m}限定符
^, $, \任何元字符、任何字符定位点和序列(即:位置和顺序)

Js正则常用方法

1、定义正则

定义正则有下面两种方式:

// 第一种
//RegExp对象。参数就是我们想要制定的规则。
let reg = new RegExp("a");
// 第二种
// 简写方法 推荐使用 书写简便、性能更好。
let reg = /a/;

2、test()

在字符串中查找符合正则的内容,若查找到返回true,反之返回false。
例:

let reg = /^ab+c*$/;
let str = "abbc";
reg.test(str);  //true

3、match()

在字符串中搜索复合规则的内容,搜索成功就返回内容,格式为数组,失败就返回null。
例:

let str = 'The fat cat eat the fish on the dish.';
let reg = /the/;
str.match(reg); //["the",index:16,...]

全局匹配匹配到多个是则在数组中按序返回,如:

let str = 'The fat cat eat the fish on the dish.';
let reg = /the/g;
str.match(reg); //["the","the"]

4、search()

在字符串搜索符合正则的内容,搜索到就返回坐标(从0开始,如果匹配的不只是一个字母,那只会返回第一个字母的位置), 如果搜索失败就返回 -1 。
例:

let str = 'abc';
let reg = /bc/;
str.search(reg);    //1

5、exec()

和match方法一样,搜索符合规则的内容,并返回内容,格式为数组。

let str = 'The fat cat eat the fish on the dish.';
let reg = /the/;
reg.exec(str); //["the",index:16]

如果是全局匹配,可以通过while循环 找到每次匹配到的信息。如:

let str = 'The fat cat eat the fish on the dish.';
let reg = /the/g;
let res = "";
while(res = reg.exec(str)){
    console.log(res);
}
/**
 * 匹配到两次
 * 第一次:
 * [
    0: "the"
    groups: undefined
    index: 16
    input: "The fat cat eat the fish on the dish."
 * ]
 *
 * 第二次:
 * [
    0: "the"
    groups: undefined
    index: 28
    input: "The fat cat eat the fish on the dish."
 * ]
 */

6、replace()

查找符合正则的字符串,就替换成对应的字符串。返回替换后的内容。
replace方法接收两个参数,第一个是正则,第二个是替换字符/回调方法,我们下面分别举例说明:
例1:

let str = 'abc';
let reg = /a/;
str.replace(reg,"A");   //"Abc"

例2:

let str = 'abc';
let reg = /a/;
str.replace(reg,function(res){
    console.log(res);   //'a'
    return "A"; //不return则会返回undefine,输出结果则会变成"undefinedbc"。
});   //"Abc"

除此以外replace还有更深入的用法,会放在后面入坑那里再说。


正则进阶(入坑)

1、零宽断言

我们先去理解零宽和断言分别是什么。
–零宽:就是没有宽度,在正则中,断言只是匹配位置,不占字符,也就是说,匹配结果里是不会返回断言本身。
–断言:俗话的断言就是“我断定什么什么”,而正则中的断言,就是说正则可以指明在指定的内容的前面或后面会出现满足指定规则的内容。
总结:
零宽断言正如它的名字一样,是一种零宽度的匹配,它匹配到的内容不会保存到匹配结果中去,最终匹配结果只是一个位置而已。
javascript只支持零宽先行断言,而零宽先行断言又可以分为正向零宽先行断言,和负向零宽先行断言。

1、 正向先行断言(正向肯定预查):
–语法:(?=pattern)
–作用:匹配pattern表达式的前面内容,不返回本身。
我们来举个栗子:

The fat cat eat the fish on the dish.

我们希望拿到fat前面的字符串The。

let str = 'The fat cat eat the fish on the dish.'
let reg = /the(?=\sfat)/gi
str.match(reg);  //["The"]

2、负向先行断言(正向否定预查):
–语法:(?!pattern)
–作用:匹配pattern表达式的前面内容,不返回本身。
那如果我们希望拿到不是fat前面的字符串The呢?很简单:

let str = 'The fat cat eat the fish on the dish.'
let reg = /the(?!\sfat)/gi
str.match(reg);  //["the","the"]

3、正向后行断言(反向肯定预查):
–语法:(?<=pattern)
–作用:匹配pattern表达式的后面的内容,不返回本身。
继续举个栗子:

This is the flower cat and the civet cat.

我们希望拿到flower后面的cat。

let str = `This is the flower cat and the civet cat.`
let reg = /(?<=flower\s)cat/
str.match(reg);  //["cat",index:19]

4、 负向后行断言(反向否定预查)

ES6

  • 列举常用的ES6特性:

  • 箭头函数需要注意哪些地方?

  • let、const、var

  • 拓展:var方式定义的变量有什么样的bug?

  • Set数据结构

  • 拓展:数组去重的方法

  • 箭头函数this的指向。

  • 手写ES6 class继承。

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

微信小程序

  • 简单描述一下微信小程序的相关文件类型?

  • 你是怎么封装微信小程序的数据请求?

  • 有哪些参数传值的方法?

  • 你使用过哪些方法,来提高微信小程序的应用速度?

  • 小程序和原生App哪个好?

  • 简述微信小程序原理?

  • 分析微信小程序的优劣势

  • 怎么解决小程序的异步请求问题?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值