正则表达式的固化分组

固化分组,又叫原子组。

语法格式:(?>…)

我们在使用非贪婪模式时,匹配过程中可能会进行多次的回溯,回溯越多,正则表达式的运行效率就越低。而固化分组就是用来减少回溯次数的。

实际上,固化分组 (?>…) 的匹配与正常的匹配并无分别,它并不会改变匹配结果。唯一的不同就是:固化分组匹配结束时,它匹配到的文本已经固化为一个单元,只能作为整体而保留或放弃,小括号内的子表达式中未使用的备用状态都会被放弃,所以回溯永远也不能选择其中的状态(因此不能参与回溯)。

javaScriptjavapython 中并不支持固化分组的语法。不过,它在 php.NET 中表现良好。

下面我们通过一个 php 的固化分组正则表达式例子来深入地理解固化分组:

假如要处理一批数据,原格式为 123.456, 因为浮点数显示问题,部分数据格式会变为 123.456000000789 这种, 现要求只保留小数点后 2~3 位,但是最后一位不能为 0,那么这个正则怎么写呢?

$str = "123.456000000789";
echo preg_replace("/(\.\d\d[1-9]?)\d*/","\\1",$str); // 123.456

以上的正则表达式,对于 123.456 这种格式的数据,将白白处理一遍,为了提高效率,我们应该将 123.456 排除在外,我们将量词 * 改成 +。如下所示:

$str = "123.456";
echo preg_replace("/(\.\d\d[1-9]?)\d+/","\\1",$str);

(.\d\d[1-9]?) 会正常匹配到 .456,而 \d+ 表示匹配大于等于 1 个由 0-9 的任意数字组成的字符串,即匹配至少一个任意数字,所以 \d+ 匹配到 6 后面的结尾处位置时,会匹配失败,然后会要求 [1-9]? 回溯到备选状态,也就是放弃匹配数字 6,让给 \d+ 去匹配,结果匹配成功,最后整个正则式匹配到字符串 .456(.\d\d[1-9]?) 匹配到 .45\d+ 匹配到 6,所以 \1 引用到的是 .45,也就是把源字符串 123.456,后面的 .456 替换成了 .45,本来保留小数点后 3 位是符合需求的,现在反而被处理成了 .45,显然 123.45 不是我们期望的匹配结果,那我们应该怎么做呢?能否让 [1-9]? 一旦匹配成功,便不再进行回溯,这里就要用到固化分组,如下所示:

$str = "123.456";
echo preg_replace("/(\.\d\d(?>[1-9]?))\d+/","\\1",$str);

(?>[1-9]?) 就是固化分组,(?>[1-9]?) 成功匹配了 6,因为 (?>[1-9]?) 是固化分组,所以 ? 产生的备选状态被放弃,此时固化分组匹配到的 6 便不能用于正则引擎的回溯。子表达式 \d+ 匹配失败,尝试回溯也失败,导致整个正则表达式第 1 次迭代匹配失败,后面会继续迭代匹配到源字符串的结尾处,最后正则引擎才停止服务,不过后面的几次迭代匹配也都是失败的,那么最终的结果就是,正则表达式没有匹配到任何东西,替换动作也没有执行,这符合我们的需求。

php 还提供了占有优先的语法,效果和固化分组一样:

$str = "123.456";
echo preg_replace("/(\.\d\d[1-9]?+)\d+/","\\1",$str);

在量词 ? 后面加个 +,就变成了占有优先量词,意为着 [1-9]?+ 匹配到 6 后,是没有备选状态的(即无法回溯),这样 \d+ 最后匹配失败,最终导致整个匹配过程失败,没有匹配到任何东西。

虽然 java 不支持固化分组的语法,但 java 也提供了占有优先的语法,同样能够避免正则回溯。如下:

String str = "123.456";
System.out.println(str.replaceAll("(\\.\\d\\d[1-9]?+)\\d+", "$1"));// 123.456

值得注意的是:java 中 replaceAll 方法需要双反斜杠 \\作为转义符号。

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

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

相关文章

Requests库基本使用

requests库基本使用基本流程python中一个基于网络请求的模块,功能强大,简单便捷,效率极高,可以取代古老的urllib模块。作用:模拟浏览器向服务器发起请求。基本流程 1.指定URL2.对指定的URL发起请求(get或post)3.获取响…

tls 使用java生成_同时使用传入和传出连接时,相互TLS身份验证存在Java问题

tls 使用java生成在大多数企业环境中,应用程序之间的连接中使用某种形式的安全通信(例如TLS或SSL)。 在某些环境中, 相互(双向)身份验证也是一项非功能性要求。 有时将其称为双向SSL或双向TLS身份验证。 因…

正则表达式的环视实际应用案例

一、千位分隔符案例&#xff08;一&#xff09; 逆序环视和顺序环视结合应用。 **需求&#xff1a;**数字格式化成用 , 分隔的货币格式。 正则表达式&#xff1a;(?n)(?<\d)(?<!\.\d*)(?(\d{3})(\.|$)) 测试代码&#xff1a; double[] data new double[] { 0,…

软件工程专插本_2021年专插本部分招生专业(拟),广科/广东理工/华商/培正/松田/工商大!...

小师姐从各专插本交流群中收集到了6所院校的2021年本科插班生拟招生专业&#xff1a;广东理工学院、广东科技学院、广东财经大学华商学院、广州大学松田学院、广东培正学院、广东工商职业技术大学。ps&#xff1a;以下只是拟招生专业&#xff0c;具体还是以考试院公布的为准。另…

Requests库实战(一)---网页采集器

网页采集器User-Agent伪装完整代码功能&#xff1a;通过动态url来实现用户输入搜索关键字&#xff0c;返回搜索到的页面。User-Agent伪装 一种反爬机制。 原理&#xff1a;网站的服务器会检测对于请求的载体身份标识&#xff0c;如果检测到请求的载体身份标识为某一款浏览器&a…

ES6 对正则表达式的扩展

文章目录修饰符 y修饰符 uECMAScript 6.0&#xff08;以下简称 ES6&#xff09;是 JavaScript 语言的下一代标准&#xff0c;已经在 2015 年 6 月正式发布了。它的目标&#xff0c;是使得 JavaScript 语言可以用来编写复杂的大型应用程序&#xff0c;成为企业级开发语言。修饰符…

transformer机制讲解_【核心代码解读】Transformer-XL

[论文] Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context​arxiv.orgMotivationTransformer在预训练阶段&#xff0c;设置了固定序列长度max_len的上下文&#xff0c;finetuning阶段&#xff0c;模型不能获取大于max_len的上下文依赖&#xff1b;Tran…

Neo4j导入:java.lang.IllegalStateException:不支持在单个导入中混合指定和未指定的组所有物...

休息片刻之后&#xff0c;我最近一直在使用Neo4j导入工具 &#xff0c;并遇到了我最初不理解的有趣的错误消息。 我有一些CSV文件&#xff0c;其中包含要导入Neo4j的节点。 它们的内容如下所示&#xff1a; $ cat people_header.csv name:ID(Person)$ cat people.csv "…

Requests库实战(二)---破解百度翻译

功能&#xff1a;爬取到页面中翻译后的文本数据 获取请求地址和请求方式 先输入dog翻译一下&#xff0c;发现是Ajax请求(动态实时刷新页面)&#xff0c;Ajax请求的数据包可以在网络的XHR中看到。找到输入dog的数据包&#xff0c;通过标头的表单数据kw:dog以及响应的结果就可以…

局部变量的赋值问题

int i 5; i 10;变量 i 在栈帧里面的局部变量表里面&#xff0c;这个局部变量表类似一个数组&#xff0c;里面包含了一些“槽位”来存放局部变量&#xff0c;i 这个变量&#xff0c;就是在局部变量表中的某一个槽位里面&#xff0c;并且 i 只会占用一个槽位&#xff0c;对变量…

php生成 sku_高并发下,php与redis实现的抢购、秒杀功能

抢购、秒杀是如今很常见的一个应用场景&#xff0c;主要需要解决的问题有两个&#xff1a;1 高并发对数据库产生的压力2 竞争状态下如何解决库存的正确减少&#xff08;"超卖"问题&#xff09;对于第一个问题&#xff0c;已经很容易想到用缓存来处理抢购&#xff0c;…

lambda :: -_无需再忙了:Lambda-S3缩略图,由SLAppForge Sigma钉牢!

lambda :: ->如果你还没有注意到了&#xff0c;我最近被唠叨试图开始使用时&#xff0c;我遭遇了陷阱AWSλ-S3正式例子 。 虽然大多数这些愚蠢的错误的指责是对我自己的懒惰&#xff0c;过度自尊和缺乏对细节的关注&#xff0c;我个人觉得&#xff0c;在开始与一家领先的无服…

Requests库实战(三)---爬取豆瓣电影详细信息

完整代码 爬取豆瓣电影的详细信息 地址&#xff1a;豆瓣电影动画 向下滑动时新增的数据也是Ajax请求&#xff0c;原理和上一个项目是一样的。唯一的不同是此处请求url携带了多个参数 import requests import json header{User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x6…

lineseparator_首选System.lineSeparator()以用Java编写系统相关的行分隔符字符串

lineseparatorJDK 7在java.lang.System类上引入了一个名为lineSeparator&#xff08;&#xff09;的新方法。 该方法不期待任何参数&#xff0c;并返回一个String &#xff0c;它表示“取决于系统的行分隔符字符串。” 此方法的Javadoc文档还指出System.lineSeparator() “始终…

JavaScript(JS)中与正则表达式有关的方法介绍

文章目录RegExpRegExp 对象的属性compiletestexecString一共有 7 个与正则表达式式相关的方法&#xff0c;这些方法分别来自于 RegExp 与 String 对象。RegExp RegExp 对象表示正则表达式, 主要用于对字符串执行模式匹配. 语法: new RegExp(pattern[, flags]) 参数 pattern …

Requests库实战(四)---爬取肯德基餐厅地址信息

功能&#xff1a;爬取查询后的肯德基餐厅的地址信息 地址&#xff1a;http://www.kfc.com.cn/kfccda/storelist/index.aspx 亮点是post请求的参数有两组&#xff1a;查询字符串参数&#xff0c;表单数据。 对于post请求,由于url中隐藏了许多参数&#xff0c;所以引入了表单数据…

显示请求_学习记录:HTTP的响应与请求amp;Curl

本文包含四个部分&#xff0c;简要介绍HTTP请求、HTTP响应、chrome开发者查看、与CURL命令。Part1&#xff1a;HTTP请求1GET请求指定的页面信息&#xff0c;并返回实体主体。2HEAD类似于get请求&#xff0c;只不过返回的响应中没有具体的内容&#xff0c;用于获取报头。3POST向…

java.线程池 线程数_如何在线程“ main”中修复异常java.lang.NoClassDefFoundError:Java中的org / slf4j / LoggerFactory...

java.线程池 线程数此错误表示您的代码或您在应用程序中使用的任何外部库都在使用SLF4J库 &#xff08;一个开放源代码日志记录库&#xff09;&#xff0c;但无法找到所需的JAR文件&#xff0c;例如slf4j-api-1.7.2.jar因此它是在线程“ main” java.lang.NoClassDefFoundError…

正则表达式实战---爬取多张图片

主要是分析网站图片的html源代码&#xff0c;来决定正则表达式如何写。 完整代码 #使用正则表达式爬取多张图片,亮点在于数据解析 #爬取网站&#xff1a;https://www.bilibili.com/read/cv11323037?fromsearch import requests import re import os image_pathimage if not …

JS(JavaScript) 使用捕获性分组处理文本模板,最终生成完整字符串

var tmp "An ${a} a ${b} keeps the ${c} away";// obj 是 json 对象 var obj {a:"apple",b:"day",c:"doctor" };/** *descript 声明定义一个函数 tmpl&#xff0c;该函数将文本模板对应的变量替换后返回 * */function tmpl(t,o){/*…