正则的高级玩法

news2024/11/25 20:36:31

在正则表达式中,括号涉及的问题比较多,所以这里单独拿出来讲。

分组

如果量词所限定的元素不是一个字符或者字符组,而是一系列字符或者子表达式,就需要使用括号将他们括起来,表示为“一组”,构成单个元素。

var regex = /(ab)+/g;
var string = "ababa abbb ababab";
console.log( string.match(regex) );  
 //  ["abab", "ab", "ababab"]

上面的例子中,量词 + 的前面的元素是 (ab) , 所以 + 所限定的是括号内 ab 这个整体。

划定多选结构的范围
多选结构, 也叫 分支结构。一般的用法: (p1|p2|p3),其中,| 表示 “或”,p1、p2 和 p3 是三个子表达式,这些子表达式也叫多选分支, 括号用来划定分支结构的范围。
注意:多选结构中括号不是必须的。如果没有括号,管道符 | 会把整个表达式当做一个多选结构。比如,要匹配 grey或gray:

var regexRight = /gr(e|a)y/;  // 匹配 grey 或 gray
var regexWrong = /gre|ay/;  // 匹配 gre 或 ay

// 正确的
console.log(regexRight.test('grey'));  // true
console.log(regexRight.test('gray'));  // true
console.log(regexRight.test('gre'));  // false

// 错误的
console.log(regexWrong.test('grey'));  // true
console.log(regexWrong.test('gre'));   // true

所以,虽然多选结构中括号不是必须的,但是,通常会搭配括号来使用。

多选结构与字符组
上面多选结构中 gr(e|a)y的例子并太好,因为可以使用更好的方式代替,那便是 gr[ae]y,那么二者什么区别呢?
二者差别还是很大的:

多选结构中每个分支都必须明确列出。而字符组可以使用 - 表示范围
大多数情况下, [abc] 要比 (a|b|c) 更高效
字符组的每个 “分支” 都必须是单个的字符,而多选结构的“分支”可以是子表达式
多选结构的分支顺序会影响到最后的配置结果
没有 排除型多选结构
引用分组
使用括号之后,正则表示会保存每个分组真正匹配的文本,等匹配成功后,可以引用这些文本。
因为这种情况下“捕获”了文本,所以这种分组叫 捕获分组,这种括号叫 捕获型括号。

通过编号引用

编号规则:
如,使用(\d{4})-(\d{2})-(\d{2})匹配日期 2018-12-30:

名称
字符20181230
表达式(\d{4})(\d{2})(\d{2})
分组编号123

注意:
如果把表达式写成:(\d){4}-(\d){2}-(\d){2},则含义完全不同,(\d){4} 表示 \d 作为单独的元素出现4次,且编号都为1。

嵌套规则:根据开括号的出现顺序来计数。(图参考《正则指引》P45,我画的有点丑)
在这里插入图片描述

括号嵌套编号规则:开括号的出现顺序
在 JavaScript 中使用

提取数据

String.prototype.match() 方法返回一个数组,数组的第一项是进行匹配的完整字符串,之后的项是捕获分组的匹配结果。

var regex = /(\d{4})-(\d{2})-(\d{2})/;
var text = '2018-12-30';
console.log(text.match(regex));
// ["2018-12-30", "2018", "12", "30", index: 0, input: "2018-12-30"]

关于 match 方法,有一个地方需要注意,返回结果与正则表达式是否包含 g 标志有关。在没有 g 标志的时候,返回值和 regex.exec() 方法相同:

var regex = /(\d{4})-(\d{2})-(\d{2})/;
var text = '2018-12-30';
console.log(regex.exec(text));
// ["2018-12-30", "2018", "12", "30", index: 0, input: "2018-12-30"]

同时,也可以使用构造函数的全局属性 $1 至 $9 来获取引用:

var regex = /(\d{4})-(\d{2})-(\d{2})/;
var text = '2018-12-30';
regex.exec(text);

console.log(RegExp.$1);  // 2018
console.log(RegExp.$2);  // 12
console.log(RegExp.$3);  // 30

replace方法-替换

比如,想把 yyyy-mm-dd 格式,替换成 mm/dd/yyyy 怎么做?
可以使用下面的三种方法:

var regex = /(\d{4})-(\d{2})-(\d{2})/;
var text = '2018-12-30';

// 1
var result1 = text.replace(regex, '$2/$3/$1');

// 2
var result2 = text.replace(regex, () => `${RegExp.$2}/${RegExp.$3}/${RegExp.$1}`);

// 3
var result3 = text.replace(regex, (str, y, m, d) => `${m}/${d}/${y}`);

console.log(result1);    // 12/30/2018
console.log(result2);    // 12/30/2018
console.log(result3);    // 12/30/2018
String.prototype.replace() 规则相对复杂,有很多玩法,了解更多 。

反向引用

在正则表达式内部引用之前(左侧)捕获分组匹配的文本,形式如:\num ,其中 num 表示编号,编号规则与之前介绍的相同。
举个例子:
比如要匹配: 2018-12-30、2018.12.30 和 2018/12/30 三种形式。
可能首先想到的是:\d{4}(-|/|.)\d{2}(-|/|.)\d{2},但是:

var regex = /\d{4}(-|\/|\.)\d{2}(-|\/|\.)\d{2}/;
var text = '2018-12.30';
console.log(regex.test(text));  // true
显然,我们不希望匹配 2018-12.30 ,我们需要前后的分隔符相同:

var regex = /\d{4}(-|\/|\.)\d{2}\1\d{2}/;
var text1 = '2018-12.30';
var text2 = '2018-12-30';
var text3 = '2018/12/30';

console.log(regex.test(text1));  // false
console.log(regex.test(text2));  // true
console.log(regex.test(text3));  // true

这里的 \1 就是对前面 (-|/|.) 的引用,表达式可视化如下:
反向引用可视化
在这里插入图片描述

反向引用的二义性:

在反向引用中,如果编号大于9就会出现二义性,如:\10 是表示第十个捕获分组呢还是表示第一个捕获分组和一个字符 0 呢?
在一些编程语言中有专门的规定来避免二义性,但是在JavaScript中并没有,JavaScript对于 \10 的处理是:

  1. 如果存在第 10 个捕获分组,则引用对应的分组
  2. 如果不存在,则引用 \1

如果,在有第 10 个捕获分组的情况下,要匹配 \1 和 字符0 的话,可以使用下面两种方法:

  • 命名分组 再使用
  • 括号将 \1 或 0 括起来,比如 (\1)0 或 \1(?:0)

命名分组

由于按编号引用分组存在一些问题,如:可读性差,不易维护,二义性等。于是出现了命名分组,使用易记忆,易辨别的名字来代替编号。
== 注意:命名分组是 ES2017 新特性。==

语法规则如下:

分组:(?)
提取:$
反向引用:\k
比如,上文的一个例子可以改为:

var regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
var text = '2018-12-30';
var result = text.replace(regex, '$<month>/$<day>/$<year>');

console.log(result);   // 12/30/2018

对于方法 String.prototype.match() 和 RegExp.prototype.exec() 也有了新玩法:

var regex = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
var text = '2018-12-30';
var matchObj = text.match(regex);

console.log(matchObj.groups);
// {year: "2018", month: "12", day: "30"}

在匹配结果中,多了 groups 属性,保存了所有命名捕获分组的匹配结果。

再来看一个反向引用的例子:

var regex = /\d{4}(?<split>-|\/|\.)\d{2}\k<split>\d{2}/;
var text = '2018-12-30';

console.log(regex.test(text));  // true

非捕获分组

括号的功能有“叠加”性。括号可以表示分组,用来构成单个元素;也可以表示多选结构;但同时,也构成了引用分组。
在仅仅需要标记范围(分组或多选结构)时,正则表达式保存已经匹配的文本会造成不必要的性能浪费。
这时候我们可以使用 非捕获型括号 (?:…)来限定分组或多选结构的范围:(?:p) 和 (?:p1|p2)。这种只用来限定范围不捕获匹配文本的分组就是 非捕获分组。

非捕获型分组的优点是性能好,缺点是不美观,可读性差。
在实际应用中,建议尽量使用非捕获分组。

原文链接:https://www.jianshu.com/p/6a7d5450e164

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/978843.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【python零基础入门学习】python基础篇之系统模块调用shell命令执行(四)

本站以分享各种运维经验和运维所需要的技能为主 《python》&#xff1a;python零基础入门学习 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8》暂未更新 《docker学习》暂未更新 《ceph学习》ceph日常问题解…

接入Websocket,自动接收CSDN短消息

最近在研究Websocket功能&#xff0c;本来想接入抖音和快手的弹幕功能&#xff0c;以及短消息功能。 在了解的过程中&#xff0c;也开发了一些测试项目。 这不是&#xff0c;就把CSDN的短消息项目给弄出来了。 直接上代码&#xff1a; # !/usr/bin python3 # -*- encodingu…

U盘插电脑没反应?学会这3个方法就够了!

“谁能帮帮我呀&#xff01;u盘里有超级重要的文件哎&#xff01;但是将u盘插电脑后一点反应都没有&#xff01;我还需要将u盘里的文件导出来呢&#xff01;” U盘&#xff08;又称闪存驱动器或USB闪存驱动器&#xff09;是我们生活中常用的便携式存储设备之一&#xff0c;但在…

Python实现猎人猎物优化算法(HPO)优化BP神经网络分类模型(BP神经网络分类算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 猎人猎物优化搜索算法(Hunter–prey optimizer, HPO)是由Naruei& Keynia于2022年提出的一种最新的…

『虫无涯→_→读书推荐02期』|全面系统的〖Effective软件测试〗带你完成所有不同类型的测试,GO

目录 我看的书 我的书评/推荐理由 书籍的作者 书籍内容 赠书活动 我看的书 首次看到这本书的封面的时候&#xff0c;我被那个数字惊呆了&#xff0c;【助理软件研发提升10倍质量】&#xff0c;这对我产生了足够了吸引力。因为这个数字是非常的客观的&#xff1b;至于书…

DAY08_MyBatisPlus——入门案例标准数据层开发CRUD-Lombok-分页功能DQL编程控制DML编程控制乐观锁快速开发-代码生成器

目录 一 MyBatisPlus简介1. 入门案例问题导入1.1 SpringBoot整合MyBatisPlus入门程序①&#xff1a;创建新模块&#xff0c;选择Spring初始化&#xff0c;并配置模块相关基础信息②&#xff1a;选择当前模块需要使用的技术集&#xff08;仅保留JDBC&#xff09;③&#xff1a;手…

@PostConstruct使用

PostConstruct是Java自带的注解&#xff0c;在方法上加该注解会在项目启动的时候执行该方法&#xff0c;也可以理解为在spring容器初始化的时候执行该方法。 从Java EE5规范开始&#xff0c;Servlet中增加了两个影响Servlet生命周期的注解&#xff0c;PostConstruc

Goland2023版新UI的debug模式调试框按钮功能说明

一、背景 Jetbrains家的IDE的UI基本都是一样的&#xff0c;debug模式的调试框按钮排列也是一致的&#xff0c;但是在我使用Goland2023版的新UI时&#xff0c;发现调试框的按钮变化还是很大的&#xff0c;有一些按钮被收起来了&#xff0c;如果看之前的博客会发现有一些文中的旧…

15年安全老兵详解《孤注一掷》里的黑客技术及杀猪盘

做为网络安全从业者&#xff0c;今天谈谈电影《孤注一掷》涉及到的相关的黑客攻防技术和场景。 电影制作方也算是用心了&#xff0c;隔壁王大娘提醒我男主张艺兴饰演的潘生与编程语言Python在读音上似乎有点弦外之音&#xff0c;有点类似或谐音。 开篇男主潘生从标准码农衬衫打…

排序算法:选择排序(直接选择排序、堆排序)

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下有关排序算法的相关知识点&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; C 语 言 专 栏&#xff1a;C语言&#xff1a;从入门到精通…

网络安全人才供需严重失衡,预计2027年缺口将扩大到300万人

网络安全法正式实施5年了。 这5年&#xff0c;是网络安全法治化体系化日趋完善的5年&#xff0c;也是我国网络安全产业黄金发展的5年。 赛迪顾问数据显示&#xff0c;2016年&#xff0c;我国网络安全市场规模为336.2亿元&#xff1b;而2021年&#xff0c;市场规模达到900多亿…

java IO流(四) 数据流 序列化流

数据流 再学习一种流&#xff0c;这种流在开发中偶尔也会用到,我们想把数据和数据的类型一并写到文件中去&#xff0c;读取的时候也将数据和数据类型一并读出来。这就可以用到数据流&#xff0c;有两个DataInputStream和DataOutputStream. DataOutputStream类 写入特定类型 D…

JS 方法实现复制粘贴

背景 以前我们一涉及到复制粘贴功能&#xff0c;实现思路一般都是&#xff1a; 创建一个 textarea 标签 让这个 textarea 不可见&#xff08;定位&#xff09; 给这个 textarea 赋值 把这个 textarea 塞到页面中 调用 textarea 的 select 方法 调用 document.execCommand…

Java逻辑控制

目录 一、顺序结构 二、分支结构 1、if语句 &#xff08;1&#xff09; 语法格式1​编辑 &#xff08;2&#xff09;语法格式2​编辑 &#xff08;3&#xff09;语法格式3 2、switch 语句 三、循环结构 1、while循环 2、break 3、continue 4、for 循环 5、do whil…

Pycharm通用设置个性化设置

Pycharm通用设置&个性化设置 通用设置取消打开Pycharm自动进入项目开启【Ctrl鼠标滑轮】放大缩小字体 个性化设置设置彩虹括号 通用设置 取消打开Pycharm自动进入项目 选择选择菜单【File】>【Settings】进入设置页面选择【Appearance & Behavior】>【System S…

dantax参数调优

dantax参数调优 1.speed调优 可能会导致数据倾斜 处理的速度不同&#xff0c;可能会导致job非常慢 举例子&#xff0c;比如总限速是每秒100条record&#xff0c;其中第一个channel速度是每秒99条record&#xff0c;第二个channel是每秒1条record&#xff0c;加起来是每条100条…

Helm Deploy Online Rancher Demo

文章目录 简介预备条件在线安装 Rancher Helm Chart选择 SSL 配置安装 cert-managerHelm 安装 Rancher验证 Rancher Server 是否部署成功 简介 Rancher 是一个开源的企业级全栈化容器部署及管理平台。已有超过 1900 万次下载&#xff0c;4000 生产环境的应用。 简单的说&…

医院如何选择跨网文件交换产品,提升业务效率?

我国医院根据国家信息安全相关法规要求&#xff0c;大多都采用网闸等隔离手段&#xff0c;将网络隔离为内网和外网&#xff0c;但网络隔离后&#xff0c;医院仍需要进行内外网间的文件交换&#xff0c;如患者的检测报告、学术研究等资料。而医院内的不同科室都存在内外网文件交…

被动元件库存“见底”,或迎涨价潮? | 百能云芯

近日&#xff0c;有消息称被动元件可能会涨价&#xff0c;这促使了被动元件相关股票的全面上涨。国内相关供应链表示&#xff0c;虽然目前没有涨价的条件&#xff0c;但经过长时间的库存消化&#xff0c;各种应用的库存几乎已经清空&#xff0c;只等待终端需求的回升。 自2021年…

软件测试/测试开发丨测试用例自动录入 学习笔记

点此获取更多相关资料 本文为霍格沃兹测试开发学社学员学习笔记分享 原文链接&#xff1a;https://ceshiren.com/t/topic/27139 测试用例自动录入 测试用例自动录入的价值 省略人工同步的步骤&#xff0c;节省时间 兼容代码版本的自动化测试用例 用例的执行与调度统一化管理…