ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
12
返回列表 发新帖
楼主: 小花鹿

[求助] 正则学习请教3

[复制链接]

TA的精华主题

TA的得分主题

发表于 2015-9-10 21:20 | 显示全部楼层
4楼5楼言简意赅,一语中的,有诗一般的韵味,真的不错。
反复读,一定能读出名堂来。

当然,两位高手如能就“为什么不能”、“如何才能”两个话题作些解读,可惠及更多后来人。

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-9-10 21:26 | 显示全部楼层
山菊花 发表于 2015-9-10 21:20
4楼5楼言简意赅,一语中的,有诗一般的韵味,真的不错。
反复读,一定能读出名堂来。

呵呵,版主真幽默,谢谢你了。

TA的精华主题

TA的得分主题

发表于 2015-9-10 21:41 | 显示全部楼层
一点都不幽默,都是大实话。
5楼结尾一句话:“而楼上用懒惰匹配模式”.*?“匹配了这些字符”,你不觉得这是一张送给你我寻找答案的门票么?
关于正则的文章网上很多,打开这些文章,搜索一下“懒惰匹配模式”,详细的答案不是有了么?

TA的精华主题

TA的得分主题

发表于 2015-9-10 22:10 | 显示全部楼层
{:soso_e176:}5楼回答很清楚了。

TA的精华主题

TA的得分主题

发表于 2015-9-10 22:47 | 显示全部楼层
失败原因:
目标文本: 在1998年又出版了windows98 ,和97一样,98也OK也很好用
正则: (?=windows)(?=\d+年).*OK(.*)
此正则可看成三个子表达式:(1)  (?=windows) ;   (2) (?=\d+年);    (3) .*OK(.*)
匹配过程:
从左至右, 在"在1998年又出版了"每个字符上测试正则的子表达式(1)都是失败的, 直到字符"w"所在位置处子表达式(1)匹配成功,这时在同一位置处测试子表达式(2),显然失败. 于是引擎继续在目标文本中移动到下一位置, 即"i"所在位置, 而引擎通过"回溯"机制,正则表达式重新回到子表达式(1)处,用子表达式(1)去"i"所在位置尝试匹配,肯定会失败.直至行尾的每个位置上子表达(1)都是失败的. 最后引擎报告结果---整体匹配失败.结束!

按题意,可以用一个更容易理解正则完成任务:
^.*?(?:windows|\d+年).*?(?:windows|\d+年).*?OK(.*)

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-9-11 01:47 | 显示全部楼层
本帖最后由 小花鹿 于 2015-9-11 10:48 编辑
liu-aguang 发表于 2015-9-10 22:47
失败原因:
目标文本: 在1998年又出版了windows98 ,和97一样,98也OK也很好用
正则: (?=windows)(?=\d+年 ...


失败原因:
目标文本: 在1998年又出版了windows98 ,和97一样,98也OK也很好用
正则: (?=windows)(?=\d+年).*OK(.*)
此正则可看成三个子表达式:(1)  (?=windows) ;   (2) (?=\d+年);    (3) .*OK(.*)
匹配过程:
从左至右, 在"在1998年又出版了"每个字符上测试正则的子表达式(1)都是失败的, 直到字符"w"所在位置处子表达式(1)匹配成功,这时在同一位置处测试子表达式(2),显然失败. 于是引擎继续在目标文本中移动到下一位置, 即"i"所在位置, 而引擎通过"回溯"机制,正则表达式重新回到子表达式(1)处,用子表达式(1)去"i"所在位置尝试匹配,肯定会失败.直至行尾的每个位置上子表达(1)都是失败的. 最后引擎报告结果---整体匹配失败.结束!
按题意,可以用一个更容易理解正则完成任务:
^.*?(?:windows|\d+年).*?(?:windows|\d+年).*?OK(.*)
.....................................................................................................分割线................................................................
第一个问题:
这种解释我看明白了,现在我用自己的话再复述一遍:
从左至右,先在“在”这个字符位置上开始,测试子表达式1,不跟windows ,所以失败,再移动到下一位置“1 “,同样也不跟windows ,所以也匹配失败,一直到“了”都是失败的,直到“w” 开始紧跟windows ,所以子表达式1匹配成功,当子表达式1匹配成功后,位置不向下移动,而是在“w” 这个位置开始尝试匹配子表达式2,也就是说从“w” 这个位置开始是不是紧跟子表达式2 ,显然不成功,然后移动到下一位置“i” ,这时再尝试子表达式1,肯定失败,由此向右,子表达式1一直是失败的,所以,最后结果是失败。
但是,如果把子表达式1改成 (?=.*?windows) ,情况就不同了:
从左至右,先在“在”这个位置上用“在”匹配.*?,成功,再匹配windows ,不成功,回溯,再用“1” 匹配.*? ,成功,再匹配windows ,不成功,再回溯,一直到“了”与.*? 匹配成功,再匹配windows ,成功,这时位置还在“在”上面,这时从“在”这个位置开始,尝试子表达式2(\d+年),先用“在”匹配子表达式2,不成功,再用“1” 匹配子表达式2,也不成功,一直到8前面的9,都不成功,但是到了“8” ,与子表达式匹配成功,这时位置仍然在“在”上面,在子表达式1 和子表达式2 成功的基础上,从“在”开始再尝试匹配子表达式3,显然是成功的,所以最终的结果是匹配成功。
其实(\d+年) 应该改成 (\d+?年)
....................................................................
上面这段表达有误,子表达式2匹配成功后,位置不应该在“在”上,而应该在“1” 上。
(\d+?年) 应该是 (\d+年)
....................................................................
第二个问题:
你所写的这个表达式 ^.*?(?:windows|\d+年).*?(?:windows|\d+年).*?OK(.*) 很好,很容易理解。
其实我事先也有个答案:(?=.*windows)(?=.*\d+年).*OK(.*) 只是效率不高,现在想想应该改成:(?=.*?windows)(?=.*?\d+年).*?OK(.*)


TA的精华主题

TA的得分主题

 楼主| 发表于 2015-9-11 02:00 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 小花鹿 于 2015-9-11 10:43 编辑
liu-aguang 发表于 2015-9-10 22:47
失败原因:
目标文本: 在1998年又出版了windows98 ,和97一样,98也OK也很好用
正则: (?=windows)(?=\d+年 ...


Sub test()
Dim reg, i&, s
s = "在1998年又出版了windows98 ,和97一样,98也OK也很好用"
Set reg = CreateObject("vbscript.regexp")
reg.Pattern = "(?=.*?windows)(?=\d+?年).*OK(.*)"
MsgBox reg.Execute(s)(0)
End Sub

我现在还是有疑问,按你这个帖子的解释过程,上面的代码结果应该是整个字符串:
在1998年又出版了windows98 ,和97一样,98也OK也很好用
而现在的结果是:
1998年又出版了windows98 ,和97一样,98也OK也很好用   (少了前面的“在”)

我怎么又解释不通了呢?

理解有误,结果是正确的,因为前两个括号匹配后,位置在“1 “ 上。

TA的精华主题

TA的得分主题

发表于 2015-9-11 08:27 | 显示全部楼层
小花鹿 发表于 2015-9-11 02:00
Sub test()
Dim reg, i&, s
s = "在1998年又出版了windows98 ,和97一样,98也OK也很好用"

1. 子表式(2)错误: 应为(?=.*?\d+年)
2. 在此题在"\d+?"使用忽略优先量词"?"是多余的,反而降低效率.
3. 整个正则前最好增加脱字符"^". 这个符号对成功匹配时效率影响小,但对失败匹配时却影响很大.它可以让引擎快速报告失败.

:::::一个良好的正则不但要能快速报告成功匹配,也能快速报告匹配失败!!!

TA的精华主题

TA的得分主题

 楼主| 发表于 2015-9-11 10:54 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2015-9-13 12:54 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
liu-aguang 发表于 2015-9-11 08:27
1. 子表式(2)错误: 应为(?=.*?\d+年)
2. 在此题在"\d+?"使用忽略优先量词"?"是多余的,反而降低效率.
3. ...

深深敬佩liu-aguang!
他写的《正则表达式入门与提高》(http://club.excelhome.net/thread-1128647-1-1.html) 非常经典,我也一直在学习中。
高手未必都能当好老师,从这次的讨论中可以看出,liu-aguang既是高手,还是个好老师。
不少人懂而不精,或者知其然而不知其所以然。好比楼主的这个问题,我也能解,但只是一知半解,让我如此清楚明白地解释出来是很难的。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-28 23:56 , Processed in 0.046358 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

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