源码网,源码论坛,源码之家,商业源码,游戏源码下载,discuz插件,棋牌源码下载,精品源码论坛

 找回密码
 立即注册
查看: 425|回复: 11

[正则表达式] 正则用(?>…)实现固化分组提高效率

[复制链接]

7万

主题

861

回帖

32万

积分

论坛元老

Rank: 8Rank: 8

积分
329525
发表于 2012-10-7 05:47:58 | 显示全部楼层 |阅读模式
用(?>…)实现固化分组(成功匹配后,回簌时不会考虑这个匹配的字符) 具体来说,使用「(?>…)」的匹配与正常的匹配并无差别,但是如果匹配进行到此结构之后(也就是,进行到闭括号之后),那么此结构体中的所有备用状态都会被放弃(不能被回溯)。
  也就是说,在固化分组匹配结束时,它已经匹配的文本已经固化为一个单元,只能作为整体而保留或放弃。括号内的子表达式中未尝试过的备用状态都不复存在了,所以回溯永远也不能选择其中的状态(至少是,当此结构匹配完成时,“锁定(locked in)”在其中的状态)。
例子:
  比如要处理一批数据,原来格式为123.456,后来因为浮点数显示问题,部分数据格式变为123.456000000789这种,,要求做到只保留小数点后面2-3位,但是,最后一位不能为0,这个正则如何写呢?(下面直接考虑小数点后面的数字),写出正则之后,我们还要用这个正则去匹配数据,把原来的数据替换成匹配的结果。

正则一、
复制代码 代码如下:
$str = preg_replace('\.(\d\d[1-9]?)\d*','\\1',$str);
//匹配结果的group1进行反向引用

很明显,这种写法,对于部分数据格式为123.456的这种格式,白白的处理了一遍,为了提高效率,我们还要对这个正则进行处理。从123.456这个字符串跟其他的比较一下,我们发现,是疑问123.456这个数据后面没数字了,所以,白白处理一遍。那好办,我们对这个正则改造一下,把后面的量词*改成+,这样对于123.45 小数点后面1,2位数字的,不会去白白处理,而且,对三位以上数字的,处理正常。其PHP代码为

正则二、
复制代码 代码如下:
$str = preg_replace('\.(\d\d[1-9]?)\d+','\\1',$str);

好了,这个正则真的没问题吗??下面,我们也分析一下这个正则的匹配过程吧。
  字符串"123.456",正则表达式为【\.(\d\d[1-9]?)\d+】,我们来看下

  首先(小数点前123不说了),
  【\.】匹配".",匹配成功,把控制权给下一个【\d】,【\d】匹配“4”成功,把控制权给第二个【\d】,这个【\d】匹配“5”成功,然后,把控制权给了【[1-9]?】,由于量词是【?】,正则表达式遵循“量词优先匹配”,而且,此处是【?】,还会留下一个回溯点。然后匹配"6"成功,然后把控制权给【\d+】,【\d+】发现后面没字符了,最遵循“后进先出”规则,回到上一个回溯点,进行匹配,这时,【[1-9]?】会交还出其匹配的字符“6”,【[1-9]?】匹配“6”成功。匹配完成了。大家发现【(\d\d[1-9]?)】匹配的结果确是"45",并不是我们想要的“456”,“6”被【\d+】匹配去了。那么,我们该如何办呢? 能否让【[1-9]?】匹配一旦成功,不进行回溯呢?这就用到了我们上面说的"固化分组", PHP(preg_replace函数)中使用的正则引擎支持固化分组,我们根据固化分组的写法,可以把代码改成如下方式

正则三、
复制代码 代码如下:
$str = preg_replace('\.(\d\d(?>[1-9]?))\d+','\\1',$str);

改成这样的话,那字符串“123.456“是不符合要求,不会被匹配的。那我们就可以实现我们的要求了。

  所以,让我们来看(\.\d\d(?>[1-9]?))\d+。
  在固化分组内,量词能够正常工作,所以如果[1-9]不能匹配,正则表达式会返回? 留下的备用状态。然后匹配脱离固化分组,继续前进到「\d+」。在这种情况下,当控制权离开固化分组时,没有备用状态需要放弃(因为在固化分组中没有创建任何备用状态)。
  如果[1-9] 能够匹配,匹配脱离固化分组之后,「? 」保存的备用状态仍然存在。但是,因为它属于已经结束的固化分组,所以会被抛弃。
  匹配‘.625'或者‘.625000'时就会发生这种情况。在后一种情况下,放弃那些状态不会带来任何麻烦,因为「\d+」匹配的是‘.625000',到这里正则表达式已经完成匹配。但是对于‘.625'来说,因为「\d+」无法匹配,正则引擎需要回溯,但回溯又无法进行,因为备用状态已经不存在了。既然没有能够回溯的备用状态,整体匹配也就失败,‘.625'不需要处理,而这正是我们期望的。
回复

使用道具 举报

1

主题

1万

回帖

93

积分

注册会员

Rank: 2

积分
93
发表于 2023-5-31 09:52:55 | 显示全部楼层
sdsadsadsadf
回复 支持 反对

使用道具 举报

41

主题

303

回帖

485

积分

中级会员

Rank: 3Rank: 3

积分
485
发表于 2024-5-29 07:29:00 | 显示全部楼层
哟哟哟哟哟以偶
精准数据获客 渗透劫持一手料商电报TG@liaoshang1
回复 支持 反对

使用道具 举报

1

主题

1万

回帖

93

积分

注册会员

Rank: 2

积分
93
发表于 2024-6-6 13:27:06 | 显示全部楼层
啊,数码撒飒飒飒飒
回复 支持 反对

使用道具 举报

0

主题

1万

回帖

0

积分

中级会员

Rank: 3Rank: 3

积分
0
发表于 2024-7-2 10:39:54 | 显示全部楼层
看看看咋么
回复 支持 反对

使用道具 举报

0

主题

2万

回帖

61

积分

注册会员

Rank: 2

积分
61
发表于 2024-8-12 04:46:30 | 显示全部楼层
问问问企鹅哇哇哇哇哇
回复 支持 反对

使用道具 举报

4

主题

2万

回帖

262

积分

中级会员

Rank: 3Rank: 3

积分
262
发表于 2024-8-23 23:05:00 | 显示全部楼层
的谁vdvdsvdsvdsdsv
回复 支持 反对

使用道具 举报

3

主题

2万

回帖

50

积分

注册会员

Rank: 2

积分
50
发表于 2024-9-1 23:46:34 | 显示全部楼层
还有人在不。。。。。。。。。。啊
回复 支持 反对

使用道具 举报

0

主题

6218

回帖

68

积分

注册会员

Rank: 2

积分
68
发表于 2024-9-15 05:52:33 | 显示全部楼层
搞个免费的用用
回复 支持 反对

使用道具 举报

0

主题

2万

回帖

0

积分

中级会员

Rank: 3Rank: 3

积分
0
发表于 2024-10-22 21:10:32 | 显示全部楼层
的vgdsvsdvdsvdsvds
回复 支持 反对

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

手机版|小黑屋|网站地图|源码论坛 ( 海外版 )

GMT+8, 2024-11-22 11:54 , Processed in 0.107868 second(s), 26 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表