[向过客提问]正则原理问题--为什么分组比断言快呢?

regex_night_02 2010-08-28 09:35:45
刚看到一个帖子:http://topic.csdn.net/u/20100828/21/4a5f44fc-d976-48af-bd9a-33ed40478ecf.html
过客兄和jutuo2009cs的答案均可以匹配。出于好奇,做了一个性能测试。发现过客兄的那个正则效率很高。引发本帖问题。
为什么分组匹配效果比断言要块那么多呢?

对比结果如下:
测试文本:
[field:name len="10"] 或 [field: name len="10"]
结果:
一共用时:1763毫秒(1.763秒) [100000次]

★表达式1:field:\s*(\S+)
执行时间:681毫秒(0.681秒) 占总时间38.63%

★表达式2:(?<=:\s*)\w+
执行时间:1082毫秒(1.082秒) 占总时间61.37%
...全文
135 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
Harrison_2009 2010-08-28
  • 打赏
  • 举报
回复
学习了,多谢逍遥,过客两位前辈!
porschev 2010-08-28
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 lxcnn 的回复:]
其实主要是回溯次数和所用的元字符匹配范围的原因

表达式二换成下面的试一下:
(?<=field:\s*?)\w+

然后再把表达式一换成下面的试一下:
field:\s*(\w+)

关于逆序环视的匹配原理,我在下面的博客中已经讲解过了
正则匹配原理之——逆序环视深入
[/Quote]

终于看完了。。
-过客- 2010-08-28
  • 打赏
  • 举报
回复
field:\s*(\S+)
匹配的debug的匹配过程共98步,多数是这样的匹配失败过程
Beginning match attempt at character 47
backtrack
Match attempt failed
两次匹配成功过程
Beginning match attempt at character 27
f
fi
fie
fiel
field
field:
field:
field: name
field: name
Match found


(?<=field:\s*)\w+
匹配的debug的匹配过程共219步,多数是这样的匹配失败过程
Beginning match attempt at character 47
ok
backtrack
backtrack
Match attempt failed
两次匹配成功过程
Beginning match attempt at character 7
ok
:
d
l
e
i
f
ok
name
Match found

可以看到在匹配失败时,回溯次数上的差异
智卓见 2010-08-28
  • 打赏
  • 举报
回复
李消遥兄,你太强了!谢谢指点!
兔子-顾问 2010-08-28
  • 打赏
  • 举报
回复
但是这里实际上并没有出现匹配失败哦。如果匹配失败的情况,回溯很要命,甚至会导致正则引擎崩溃。但现在成功的时候,第二个为什么也慢呢?
龍月 2010-08-28
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 lxcnn 的回复:]
其实主要是回溯次数和所用的元字符匹配范围的原因

表达式二换成下面的试一下:
(?<=field:\s*?)\w+

然后再把表达式一换成下面的试一下:
field:\s*(\w+)

关于逆序环视的匹配原理,我在下面的博客中已经讲解过了
正则匹配原理之——逆序环视深入
[/Quote]
顶之
-过客- 2010-08-28
  • 打赏
  • 举报
回复
回溯次数的差异体现在两个方面:
1、成功匹配时,表达式1不需要回溯,而表达式2要进行回溯
2、这两个表达式都是要遍历尝试所有位置的,在这个例子中,表达式1只需要尝试匹配1个字符就可以报告匹配失败,而表达式2则要进行更多的回溯和尝试

另外,元字符的范围也是一个要考虑的因素
为什么明确的字符匹配的速度快?因为只需要比较一次
而\w则需要比较多次,范围更大的\S比较的次数就更多
所以如果能够明确源字符串范围的情况下,尽量使用表示范围小的元字符或子表达式
-过客- 2010-08-28
  • 打赏
  • 举报
回复
其实主要是回溯次数和所用的元字符匹配范围的原因

表达式二换成下面的试一下:
(?<=field:\s*?)\w+

然后再把表达式一换成下面的试一下:
field:\s*(\w+)

关于逆序环视的匹配原理,我在下面的博客中已经讲解过了
正则匹配原理之——逆序环视深入
regex_night_02 2010-08-28
  • 打赏
  • 举报
回复
你贴的那个是js的,js中本就不支持(?<=exp)
回溯,不同情况意义不同的。
等客客兄。
Peter200694013 2010-08-28
  • 打赏
  • 举报
回复
不是特别懂
这有篇效率分析的文章
http://bbs.phpchina.com/viewthread.php?tid=189933

//等过客前辈
regex_night_02 2010-08-28
  • 打赏
  • 举报
回复
field:\s*(\S+)
这个不用说,匹配过程很简单
匹配常量字符f
常量字符i
常量字符e
常量字符l
常量字符d
常量字符:
范围匹配\s,各种符号
匹配所有非字符,创建堆栈保存匹配(\S+)
整个过程是一个循环完成。


(?<=:\s*)\w+
这个么…
断言的匹配过程还不了解,不知道是不是先匹配\w,匹配成功,则回溯查看前一个char是否符合(?<=exp)中的匹配,所以\w+匹配到name4个字母,则需要回溯4次,而每次回溯都将需要重新匹配:\s*,导致了性能的降低?

不知道我这样理解对不对。
regex_night_02 2010-08-28
  • 打赏
  • 举报
回复
也许说是下面的没检查field。我加上后对比结果为:

一共用时:1742毫秒(1.742秒) [100000次]

★表达式1:field:\s*(\S+)
执行时间:661毫秒(0.661秒) 占总时间37.94%

★表达式2:(?<=field:\s*)\w+
执行时间:1081毫秒(1.081秒) 占总时间62.06%

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧