javascript正则深入以及10个非常有意思的正则实战

简介: 熟悉我的朋友可能会知道,我一向是不写热点的。为什么不写呢?是因为我不关注热点吗?其实也不是。有些事件我还是很关注的,也确实有不少想法和观点。 但我一直奉行一个原则,就是:要做有生命力的内容。

前言


熟悉我的朋友可能会知道,我一向是不写热点的。为什么不写呢?是因为我不关注热点吗?其实也不是。有些事件我还是很关注的,也确实有不少想法和观点。 但我一直奉行一个原则,就是:要做有生命力的内容


对于前端工程师来说, 正则表达式也许是javascript语言中最晦涩难懂的, 但是也往往是最简洁的.工作中遇到的很多问题,诸如搜索,查找, 高亮关键字等都可以使用正则轻松解决,所以有句话说的好:


正则用的好, 加班远离我.


今天笔者就复盘一下javascript正则表达式的一些使用技巧和高级API, 并通过几个实际的案例,来展现正则表达式的魅力.如果大家觉得正则表达式理解起来很麻烦,也可以使用如下在线网站, 只需要输入你的正则表达式, 它就能以图形的方式将你的正则展示出来:



你将收获


  • 模式匹配的用法(x)
  • 非捕获括号的模式匹配(?:x)
  • 先行断言x(?=y)
  • 后行断言(?<=y)x
  • 正向否定查找x(?!y)
  • 反向否定查找(?
  • 字符集合和反向字符集合的用法[xyz]/[^xyz]
  • 词边界和非单词边界匹配/b/B
  • 空白字符/非空白字符匹配/s/S
  • 单字字符/非单字字符匹配/w/W
  • 正则10大应用案例


正文


对于正则的基本用法笔者这里就不总结了,这里重点介绍一些比较有用且难懂的知识点.在最后笔者会写10个经典的正则案例, 供大家学习参考, 或者在工作中直接使用.



以上几点应用笔者在下文中会写几个例子来讲解.


模式匹配的用法(x)



模式匹配主要用来匹配某一类字符串并记住匹配项.


案例:


letstr='xuxi is xuxi is'letreg=/(xuxi) (is) \1 \2/greg.test(str)  // true    (1)str.replace(reg, '$1 $2')  // xuxi is  (2)

解释: 其中括号被称为捕获括号, 模式中的 \1 和 \2 表示第一个和第二个被捕获括号匹配的子字符串,即 xuxi 和 is,匹配了原字符串中的后两个单词, 因此(1)中运行的结果为true. 当我们在字符串中使用replace时, 我们可以使用1,1, 1,2这样的方式获取第n个匹配项,并用来替换字符串. 如(2)中的运行结果.


非捕获括号的模式匹配(?:x)



主要用来匹配某一类字符串但不记住匹配项.


案例:


letstr='xuxixuxi'letreg=/(?:xuxi){1,2}/greg.test(str)  // true    (1)


解释: 其中(?:)被称为非捕获括号, 我们可以使用它匹配一组字符但是并不记住该字符,一般用来判断某类字符是否存在于某字符串中.


先行断言x(?=y)



先行断言: 匹配'x'仅仅当'x'后面跟着'y'.


案例:

letstr='王者融化'letreg=/王(?=者)/reg.test(str)  // true    (1)


解释: /王(?=者)/会匹配到"王"仅当它后面跟着"者".但是"者"不属于匹配结果的一部分.

后行断言(?<=y)x



后行断言: 匹配'x'仅当'x'前面是'y'.


案例:

letstr='xuxiA'letreg=/(?<=xuxi)A/reg.test(str)  // true    (1)

解释: /(?<=xuxi)A/会匹配到A仅当它前面为xuxi.但是xuxi不属于匹配结果的一部分.


正向否定查找x(?!y)



正向否定查找: 仅仅当'x'后面不跟着'y'时匹配'x'.


案例:

letstr='3.1415'letreg=/\d+(?!\.)/reg.exec(str)  // [1415]   (1)


解释: 其中/\d+(?!.)/匹配一个或多个数字,当且仅当它后面没有小数点时, 所以(1)中执行后会匹配到1415而不是3.1415


反向否定查找(?



反向否定查找: 仅仅当'x'前面不是'y'时匹配'x'.


案例:

letstr='3.1415'letreg=/(?<!\.)\d+/reg.exec(str)  // [3]    (1)

解释: /(?


字符集合和反向字符集合的用法 [xyz] / [^xyz]



[xyz]: 一个字符集合。匹配方括号中的任意字符,包括转义序列。你可以使用破折号(-)来指定一个字符范围。

[^xyz]: 一个反向字符集。也就是说,它匹配任何没有包含在方括号中的字符。你可以使用破折号(-)来指定一个字符范围。任何普通字符在这里都是起作用的


案例:


letstr='abcd'letreg1=/[a-c]+/letreg2=/[^d]$/reg1.test(str)  // true    (1)reg2.test(str)  // false    (2)




解释: (1)中将返回true因为字符串中包含a-c中的字符, (2)中奖返回false, 因为字符串结尾为d, 但正则reg2需要匹配结尾不为d的字符串.


词边界和非单词边界匹配\b\B



\b 匹配一个词的边界。一个词的边界就是一个词不被另外一个“字”字符跟随的位置或者前面跟其他“字”字符的位置,例如在字母和空格之间。注意,匹配中不包括匹配的字边界。换句话说,一个匹配的词的边界的内容的长度是0。

\B 匹配一个非单词边界。匹配如下几种情况:


(1)字符串第一个字符为非“字”字符 (2)字符串最后一个字符为非“字”字符 (3)两个单词字符之间 (4)两个非单词字符之间 (5)空字符串


案例:


letstr='xuxi'letreg1=/xi\b/letreg2=/xu\B/reg1.exec(str)  // [xi]    (1)reg2.exec(str)  // [xu]    (2)



解释: (1)中匹配到了单词边界,即xi, 为该字符串的末尾.(2)中应为xu为非单词边界,所以会被其匹配到.


空白字符/非空白字符匹配\s\S



\s: 匹配一个空白字符,包括空格、制表符、换页符和换行符.

\S: 匹配一个非空白字符


案例:

letstr='xuxi is'letreg1=/.*\s/gletreg2=/\S\w*/greg1.exec(str)  // [xuxi]    (1)reg2.exec(str)  // [xuxi]    (2)



解释: (1)和(2)中执行之后都将匹配xuxi, 一个是空白字符之前的匹配, 一个是非空白字符的匹配.


单字字符/非单字字符匹配\w/W



\w: 匹配一个单字字符(字母、数字或者下划线)。等价于 [A-Za-z0-9_]。

\W: 匹配一个非单字字符。等价于 [^A-Za-z0-9_]




由于以上2种模式比较简单,这里就不一一介绍了.


正则10大应用案例



接下来笔者将总结几个使用正则的实际应用,供大家学习和参考.


1. 去除字符串内指定元素的标签


functiontrimTag(tagName, htmlStr) {
letreg=newRegExp(`<${tagName}(\\s.*)*>(\\n|.)*<\\/${tagName}>`, "g")
returnhtmlStr.replace(reg, '')
}

2. 短横线命名转驼峰命名

// 短横线转驼峰命名, flag = 0为小驼峰, 1为大驼峰functiontoCamelCase(str, flag=0) {
if(flag) {
returnstr[0].toUpperCase() +str.slice(1).replace(/-(\w)/g, ($0, $1) =>$1.toUpperCase())
  }else {
returnstr.replace(/-(\w)/g, ($0, $1) =>$1.toUpperCase())
  }
}

3. 实现一个简单的模板引擎


关于实现一个模板引擎, 实现中用到了大量的正则,建议感兴趣的可以直接看实现一个简单的模板引擎.


4. 去除字符串中的空格符

functiontrimAll(str) {
returnstr.replace(/\s*/g,"")
}

5. 判断指定格式的数据输入合法性

functionnumCheck(str, specialNum) {
if(str.indexOf(',') >-1) {
returnstr.split(',').every(item=>this.numCheck(item));
  } else {
returnstr.split(specialNum).length===2;
  }
}

6. 去除url参数字符串中值为空的字段

// 去除url参数字符串中值为空的字段consttrimParmas= (parmaStr:string='') => {
returnparmaStr.replace(/((\w*?)=&|(&\w*?=)$)/g, '')
}

7. 将浏览器参数字符串转化为参数对象

functionunParams(params='?a=1&b=2&c=3') {
letobj= {}
params&&params.replace(/((\w*)=([\.a-z0-9A-Z]*)?)?/g, (m,a,b,c) => {
if(b||c) obj[b] =c  })
returnobj}

8. 计算字符串字节数

/** * 计算字符串字节数 * @param str * @desc 一个中文占2个字节, 一个英文占一个字节 */functioncomputeStringByte(str) {
letsize=0,
strArr=str.split(''),
reg=/[\u4e00-\u9fa5]/// 判断是否为中文for(leti=strArr.length; i--; i>=0) {
if(reg.test(strArr[i])) { 
size+=2    }else {
size+=1    }
  }
returnsize}

9. 匹配是否包含中文字符

functionhasCn(str) {
letreg=/[\u4e00-\u9fa5]/greturnreg.test(str)
}

10. 实现搜索联想功能

functionsearchLink(keyword) {
// 模拟后端返回数据letlist= ['abc', 'ab', 'a', 'bcd', 'edf', 'abd'];
letreg=newRegExp(keyword, 'i');
returnlist.filter(item=>reg.test(item))
}


目录
相关文章
|
1月前
|
JavaScript
Nest.js 实战 (十一):配置热重载 HMR 给服务提提速
这篇文章介绍了Nest.js服务在应用程序引导过程中,TypeScript编译对效率的影响,以及如何通过使用webpackHMR来降低应用实例化的时间。文章包含具体教程,指导读者如何在项目中安装依赖包,并在根目录下新增webpack配置文件webpack-hmr.config.js来调整HMR相关的配置。最后,文章总结了如何通过自定义webpack配置来更好地控制HMR行为。
|
2月前
|
缓存 中间件
Nest.js 实战 (九):使用拦截器记录用户 CURD 操作日志
这篇文章介绍了在Nest.js中如何实现记录用户CURD操作的需求。首先解释了什么是拦截器以及拦截器的作用,然后通过创建Prisma模型,添加Log模型,并通过编写LoggerInterceptor拦截器,实现了记录用户操作的功能。最后通过效果演示和总结,强调了使用拦截器实现此功能的有效性。
|
21天前
Nest.js 实战 (十三):实现 SSE 服务端主动向客户端推送消息
这篇文章介绍了在Nest.js应用中使用Server-Sent Events (SSE)的技术。文章首先讨论了在特定业务场景下,为何选择SSE而不是WebSocket作为实时通信系统的实现方式。接着解释了SSE的概念,并展示了如何在Nest.js中实现SSE。文章包含客户端实现的代码示例,并以一个效果演示结束,总结SSE在Nest.js中的应用。
Nest.js 实战 (十三):实现 SSE 服务端主动向客户端推送消息
|
10天前
|
JavaScript 前端开发 安全
js逆向实战之烯牛数据请求参数加密和返回数据解密
【9月更文挑战第20天】在JavaScript逆向工程中,处理烯牛数据的请求参数加密和返回数据解密颇具挑战。本文详细分析了这一过程,包括网络请求监测、代码分析、加密算法推测及解密逻辑研究,并提供了实战步骤,如确定加密入口点、逆向分析算法及模拟加密解密过程。此外,还强调了法律合规性和安全性的重要性,帮助读者合法且安全地进行逆向工程。
44 11
|
2月前
|
SQL 运维 监控
Nest.js 实战 (十):使用 winston 打印和收集日志记录
这篇文章介绍了在Nest服务中如何使用Winston记录日志。文章首先强调了日志记录在后台服务中的重要性,接着提到Nest默认的内部日志记录器,并指出可以通过@nestjs/common包中的Logger类来全面控制日志系统的行为。文章还提到,为了在生产环境中实现更高级的日志功能,可以使用如Winston之类的Node.js日志包。接下来,文章介绍了如何在Nest服务中使用Winston记录日志,包括安装相关依赖、创建winston配置文件以及实现简单的日志记录示例。最后,文章指出更高级的自定义日志功能需要读者自己去探索。
Nest.js 实战 (十):使用 winston 打印和收集日志记录
|
23天前
Nest.js 实战 (十二):优雅地使用事件发布/订阅模块 Event Emitter
这篇文章介绍了在Nest.js构建应用时,如何通过事件/发布-订阅模式使应用程序更健壮、灵活、易于扩展,并简化服务间通信。文章主要围绕@nestjs/event-emitter模块展开,这是一个基于eventemitter2库的社区模块,提供了事件发布/订阅功能,使得实现事件驱动架构变得简单。文章还介绍了如何使用该模块,包括安装依赖、初始化模块、注册EventEmitterModule、使用装饰器简化监听等。最后总结,集成@nestjs/event-emitter模块可以提升应用程序的事件驱动能力,构建出更为松耦合、易扩展且高度灵活的系统架构,是构建现代、响应迅速且具有高度解耦特性的Nest.
|
2月前
|
JavaScript 前端开发
JavaScript基础&实战(1)js的基本语法、标识符、数据类型
这篇文章是JavaScript基础与实战教程的第一部分,涵盖了JavaScript的基本语法、标识符、数据类型以及如何进行强制类型转换,通过代码示例介绍了JS的输出语句、编写位置和数据类型转换方法。
JavaScript基础&实战(1)js的基本语法、标识符、数据类型
|
2月前
|
JavaScript 数据安全/隐私保护 Python
网易云音乐搜索接口JS逆向: Params、encSecKey加密和AES实战
网易云音乐搜索接口JS逆向: Params、encSecKey加密和AES实战
43 4
|
2月前
|
前端开发 JavaScript 开发者
前端JS按钮点击事件、跳出弹窗、遮罩的实战示例
本文提供了一个前端JS按钮点击事件、弹出式窗口和遮罩层的实战示例,包括HTML、CSS和JavaScript的具体实现代码,以及功能解析,演示了如何实现按钮点击后触发弹窗显示和遮罩层,并在2秒后自动关闭或点击遮罩层关闭弹窗的效果。
前端JS按钮点击事件、跳出弹窗、遮罩的实战示例
|
2月前
|
JavaScript 前端开发 安全
JS 混淆解析:JS 压缩混淆原理、OB 混淆特性、OB 混淆JS、混淆突破实战
JS 混淆解析:JS 压缩混淆原理、OB 混淆特性、OB 混淆JS、混淆突破实战
46 2