正则表达式中?=、?!、?<=、?<!、?:的理解与应用举例

news/2024/5/24 13:10:02/ 标签: 正则表达式

正则表达式就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个规则字符串,这个规则字符串表达对字符串的一种过滤逻辑,这篇文章主要给大家介绍了关于正则表达式中?=、?!、?<=、?<!、?:的理解与应用举例的相关资料,需要的朋友可以参考下

1. 先看一下比较官方的解释

  • (?=pattern):正向先行断言,表示匹配位置后面必须紧跟着满足 pattern 的字符串,但不包括这个字符串在匹配结果中。
  • (?!pattern):负向先行断言,表示匹配位置后面不能紧跟着满足 pattern 的字符串,也不包括这个字符串在匹配结果中。
  • (?<=pattern):正向后行断言,表示匹配位置前面必须是满足 pattern 的字符串,但不包括这个字符串在匹配结果中。
  • (?<!pattern):负向后行断言,表示匹配位置前面不能是满足 pattern 的字符串,也不包括这个字符串在匹配结果中。
  • (?:pattern):非捕获型分组,表示将 pattern 包含在一个分组中,但不把这个分组的匹配结果保存到分组编号中。这个分组通常用于表示可选的或重复的子表达式,或者是限制量词的作用范围,而不需要把它们的匹配结果单独提取出来。

2. 再看一下比较通俗易懂的解释:

  • RegExp1(?=RegExp2)  匹配后面是RegExp2 的 RegExp1
  • RegExp1(?!RegExp2)  匹配后面不是RegExp2 的 RegExp1
  • (?<=RegExp2)RegExp1  匹配前面是RegExp2 的 RegExp1
  • (?<!RegExp2)RegExp1  匹配前面不是RegExp2 的 RegExp1
  • (?:RegExp)  这个等下单独解释,与上面的不太一样

是不是有点明白了,其实?=、?!、?<=、?<!的意思可以理解为 if 判断,即只有先通过它们(RegExp2)的判断之后,才可以获取到正则(RegExp1)的匹配结果。

3. 零宽度断言

?=、?!、?<=、?<!其实就是正则表达式中的零宽度断言,以上面的举例来解释↓

 RegExp2匹配到的内容是不会返回的,也不会消耗匹配到的字符,只会返回RegExp1的匹配结果,这就是零宽度断言,零宽度断言在正则表达式中非常有用,因为它们可以在不改变匹配结果的情况下,对匹配位置前后的内容进行限制或判断。

4. ?: 的解释

(?:) 并不是零宽度断言,而是非捕获组,它跟普通的括号 () 的区别在于,它不会保存匹配到的内容,但是它仍然会消耗字符并返回匹配内容,只是不会保存匹配结果。

  • ()表示捕获分组,它会把匹配到的内容保存到内存中,开发者可以使用$n(n是一个数字)来代表第n个()中匹配到的内容
  • (?:)表示非捕获组,它匹配的内容不会被保存,所以无法使用$n获取,但也因为没有被保存所以节省了一部分内存空间

二、举例

?=

1

2

'我喜欢苹果'.replace(/我喜欢(?=苹果)/,'我讨厌') // 匹配 我喜欢苹果 中的 我喜欢 并替换为 我讨厌,因为是零宽度断言所以不包含苹果,故结果为 我讨厌苹果

'我喜欢橘子'.replace(/我喜欢(?=苹果)/,'我讨厌') // 我喜欢后面不是苹果,所以这里正则未通过,匹配不到任何内容,故结果仍为 我喜欢橘子

?!

1

2

'我喜欢苹果'.replace(/我喜欢(?!苹果)/,'我讨厌') // 匹配后面不是苹果的我喜欢,正则未通过,故结果仍为 我喜欢苹果

'我喜欢橘子'.replace(/我喜欢(?!苹果)/,'我讨厌') // 正则通过,匹配到 我喜欢 进行替换,因为是零宽度断言所以橘子不在匹配结果中,故结果为 我讨厌橘子

?<=

1

2

'我喜欢苹果'.replace(/(?<=我喜欢)苹果/,'西红柿') // 匹配到 苹果 ,故结果为 我喜欢西红柿

'我喜欢橘子'.replace(/(?<=我喜欢)苹果/,'西红柿') // 匹配不通过,故结果仍为 我喜欢橘子

?<

1

2

'我讨厌苹果'.replace(/(?<!我喜欢)苹果/,'西红柿') // 匹配到 苹果 ,故结果为 我讨厌西红柿

'我喜欢苹果'.replace(/(?<!我喜欢)苹果/,'西红柿') // 匹配不通过,故结果仍为 我喜欢苹果

?:

1

'hello world'.replace(/(?:hello) (world)/,'$1') // 匹配内容为hello world,但是hello并没有被保存,因此$1取的是world,故结果为world

三、特殊情况

正则平时我们很少会自己写,一般都是复制别人的~~~(别人的才是最好的)。然后就经常看到一种写法,比如:

/(?=.*[A-Z])[A-Za-z]{5,10}/

这时候可能有些人就想,咦,(?=)不都是符合条件后匹配它前面的内容吗?这里为什么能放在开头 呢,他前面没内容啊?其实大家可以这么理解,当(?=)前面没有内容,或者说(?=)被放在正则开头使用时,(?=)的作用就相当于检索全部内容是否符合它的要求,如果不符合也就没必要继续向后匹配了,这就很像if判断,只有当条件为true时,才能执行后面的内容。

所以这里的正则意为:先检查内容中是否至少包含一个大写字母,如果有,则继续检查并匹配5~10个大小写字母,将这5~10个大小写字母作为结果返回。

四、实例应用

姓名脱敏(添加*号)

1

'李小龙'.replace(/(?<=[\u4e00-\u9fa5])[\u4e00-\u9fa5]/g, '*') // 李**

手机号/银行账号脱敏

1

'13912345678'.replace(/(?<=\d{3})\d(?=\d{3})/g, '*') // 139*****678

强密码规则校验

1

2

// 密码不能为空,8-30位,至少包含一个大写字母、小写字母、数字、特殊字符

/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[\W_])(?!.*[\u4e00-\u9fa5])(?!\s)[a-zA-Z0-9\W_]{8,30}$/

“?”的几种用法

  • “?”元字符规定其前导对象必须在目标对象中连续出现零次或一次。
  • 当该字符紧跟在任何一个其他限制符(*,+,?,{n},{n,},{n,m})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串“oooo”,“o+?”将匹配单个“o”,而“o+”将匹配所有“o”。
  • (?:pattern) ——匹配pattern但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分是很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
  • (?=pattern)——正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
  • (?!pattern)——正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
  • (?<=pattern)——反向肯定预查,与正向肯定预查类拟,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。
  • (?<!pattern)——反向否定预查,与正向否定预查类拟,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。
  • (?i)——该表达式右边的字符忽略大小写
  • (?-i)——该表达式右边的字符区分大小写
  • (?i:x)——x 忽略大小写
  • (?-i:x)——x 区分大小写
  • ?和懒惰匹配——尽可能少的匹配,例如:源字符串str=“dxxddxxd”中,d\w*?会匹配 dx,而d\w*?d会匹配 dxxd。

总结 

到此这篇关于正则表达式中?=、?!、?<=、?<!、?:的理解与应用举例的文章就介绍到这了,更多相关正则表达式?=、?!、?<=、?<!、?:内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!


http://www.ppmy.cn/news/1424563.html

相关文章

深度 | 践行绿色健康可持续发展,这家企业提供了价值范本

文 | 螳螂观察 作者 | 余一 近段时间以来&#xff0c;小米SU7热度一直不减&#xff0c;在展露小米强大品牌号召力的同时&#xff0c;也侧面体现出了当前消费者对于新能源汽车的喜爱。 而消费者选择新能源汽车时&#xff0c;环保因素也起到了至关重要的作用。像前几日&#x…

【2024官方文档版】React-描述IU

系列文章目录 一、快速入门【基础】 二、描述IU 文章目录 系列文章目录二、描述IU1.第一个组件1.1 组件是什么?1.2 构建组件的方法1.3嵌套和组织组件1.4课后作业1.5 小结: 2.组件的导入导出2.1根组件文件2.2 导入导出文件 3. 使用JSX书写标签语言3.1 将HTML转化为JSX3.2作业 …

2024年大唐杯备考

努力更新中…… 第一章 网络架构和组网部署 1.1 5G的网络整体架构 5G网络中的中传、回传、前传&#xff08;这里属于承载网的概念&#xff09; CU和DU之间是中传 BBU和5GC之间是回传 BBU和AAU之间是前传&#xff08;这个好记&#xff09; 这里竟然还藏了MEC&#xff08;…

Excel/WPS超级处理器,提取汉字/字母/数字

在职场工作中&#xff0c;经常会遇到单元格中有汉字&#xff0c;数字&#xff0c;字母三者的自由组合&#xff0c;但往往只需要其中的一者&#xff0c;如何快速提取呢&#xff0c;超级处理器&#xff0c;提供了4个功能可选。 超级处理器下载与安装 1&#xff09;分离字符 将…

数据结构--顺序栈

一.相关概念: 1.栈和队列是操作受限的线性表,是限定性的数据结构; 2.栈分为顺序栈和链式栈 3.栈只能在一端进行操作(插入,删除); 4.栈是限定仅在表尾进行插入或删除操作的线性表.因此,对栈来说,表尾端有其特殊含义,称为栈顶(top),相应地,表头端称为栈底(bottom). 5.不含元素地…

IP证书申请流程

目录 域名与IP的关系 SSL证书绑定域名还是绑定IP&#xff1f; IP证书支持免费申请吗&#xff1f; 如何申请IP地址证书 IP类型的SSL证书&#xff0c;又称之为IP SSL&#xff0c;这种SSL证书是专门用于公网IP地址验证的一种数字证书。 主要功能就是解决IP地址明文传输的安全…

Python基础:【练手小实验系列】字符串及正则表达式

文章目录 题目练习题1: 反转字符串练习题2: 字符频率统计练习题3: 验证电子邮件地址练习题4: 寻找字符串中的所有数字练习题5: 简单的Markdown解析器参考答案练习题1: 反转字符串练习题2: 字符频率统计练习题3: 验证电子邮件地址练习题4: 寻找字符串中的所有数字练习题5: 简单的…

CSS单位选择的艺术:何时何地选用何种单位

CSS单位作为网页样式设计的基石&#xff0c;直接影响着元素尺寸、间距、字体大小等视觉呈现。选择合适的单位对于构建响应式、跨设备兼容且易于维护的界面至关重要。本文将深入分析各类CSS单位&#xff0c;并探讨在不同场景下应选用何种单位&#xff0c;同时揭示各单元的优缺点…

自动化运维工具Ansible模块的介绍与使用

文章目录 第1章 ansible介绍1.什么是ansible2.为什么需要ansible3.如何学习ansible 第2章 Ansible安装部署第3章 Ansible主机清单1.什么是主机清单2.主机分组执行3.所有的主机都执行4.SSH使用密码连接并且端口号不是225.同组主机SSH端口号不一样&#xff0c;账号密码也不一样6.…

责任链模式学习进阶--一起学习吧之数据库

上一篇学习了责任链的基本定义和特点 https://mp.csdn.net/mp_blog/creation/editor?not_checkout1&spm1015.2103.3001.8012 本文继续对责任链模式进行深入学习 一、实现过程 责任链模式的实现过程可以分为以下几个步骤&#xff1a; 定义抽象处理者角色&#xff08;Ha…

国产32位高性价比单片机 XL32F003,最高64 K flash和8 K SRAM

XL32F003系列单片机是32 位 ARMCortex- M0 内核单片机&#xff0c;1.7 V~5.5 V宽工作电压&#xff0c;工作温度范围为-40 C~85 C。最高64 Kbytes flash和8 Kbytes SRAM存储器&#xff0c;主频最高32 MHz。有SOP8/SOP14/SOP16/TSSOP20/SSOP24/QFN20/QFN32多种封装可以选择。XL32…

python把字典值转成浮点型数据

python把字典值转成浮点型数据 1、流程 1、读完数据,转成字典 2、遍历字典,使用正则判断字典值是否为浮点型字符串 3、使用eval把字符串转成浮点型2、代码 """ @contact: 微信 1257309054 @file: test.py @time: 2024/4/19 18:30 @author: LDC ""…

记一次普通的单表查询sql优化,去掉文件排序

一现象&#xff1a; 有空观察了线上某个sql语句执行计划&#xff0c;发现在500多毫秒左右&#xff0c;打算进行下优化。 二步骤&#xff1a; 对查询列assessment_periodic_id、assessment_user_id、create_time添加了组合索引并指定了倒叙。加入create_time 使查询结果不需要在…

汽车充电桩充电效率的四大决定因素

随着电动汽车的快速普及&#xff0c;交流充电桩作为电动汽车的充电基础设施&#xff0c;其充电效率受到了广泛的关注。接下来&#xff0c;我们将深入探讨交流充电桩的充电效率&#xff0c;包括充电效率的定义、影响因素以及提升方法。 充电效率的定义 交流充电桩的充电效率指的…

web3项目自动连接小狐狸以及小狐狸中的各种“地址”详解

刚做web3的时候&#xff0c;比较迷糊的就是人们口中说的各种地址&#xff0c;小狐狸钱包地址&#xff0c;私钥地址&#xff0c;跳转地址&#xff0c;接口地址&#xff0c;交易地址&#xff0c;等等XX地址&#xff0c;常常感觉跟做链的同事们说话不在一个频道。 这一小节&#x…

ActiveMQ 任意文件上传漏洞复现

一、使用弱口令登陆 ​ 访问 http://ip:8161/admin/ 进入admin登陆页面&#xff0c;使用弱口令登陆&#xff0c;账号密码皆为 admin&#xff0c;登陆成功后&#xff0c;headers中会出现验证信息 ​ 如&#xff1a; Authorization: Basic YWRtaW46YWRtaW4 # 二、利用PUT协议上…

博客文章:AWS re:Invent 2023 新产品深度解析 - 第四部分

TOC &#x1f308;你好呀&#xff01;我是 是Yu欸 &#x1f30c; 2024每日百字篆刻时光&#xff0c;感谢你的陪伴与支持 ~ &#x1f680; 欢迎一起踏上探险之旅&#xff0c;挖掘无限可能&#xff0c;共同成长&#xff01; 写在最前面 去年发布文章的一部分&#xff0c;由于内…

深度解析CSS clip-path属性:塑造网页元素的无界形态

在网页设计领域&#xff0c;CSS clip-path 属性犹如一把无形的剪刀&#xff0c;赋予设计师精准裁剪元素可视区域的能力。它通过定义一个路径来决定元素内容的显示范围&#xff0c;突破矩形边界的束缚&#xff0c;实现各种富有创意和动态变化的形状展示。本文将深入剖析 clip-pa…

区块链媒体推广的8个成功案例解析-华媒舍

区块链领域作为一个新兴行业&#xff0c;媒体推广对于项目的成功发展起着至关重要的作用。本文将从八个成功案例中来分析区块链媒体推广的重要性和成功策略。 1. 媒体报道对于区块链项目的重要影响 媒体报道是提升区块链项目知名度和用户认可度的重要手段。对于区块链项目来说…

分享2024 golang学习路线

写在前面 Go语言&#xff08;也称为Golang&#xff09;是Google开发的一种静态强类型、编译型语言&#xff0c;它具有简洁、快速、安全、并发等特点&#xff0c;尤其适合构建大型软件、微服务架构和云平台服务。Go的学习曲线相对平缓&#xff0c;社区活跃&#xff0c;是现代编…