ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: ggmmlol

[Excel 程序开发] [第127期]替换特定规则范围内的字符[已总结评分]

[复制链接]

TA的精华主题

TA的得分主题

发表于 2019-12-12 17:06 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
ggmmlol 发表于 2019-12-12 16:31
上一次我出的那个正则练习题的帖子的48楼,我专门用红字体提到“要优先排除干扰字符,然后在剩余的范围内 ...

非也非也。
水平不到家,我乱七八糟拼凑学来的正则本就粗糙,这点自知之明还是有的。
这句可不是什么瞎谦虚。可能老师不记得,我第一次在这个论坛里发关于正则的求助贴,还是老师给推荐的30分钟入门。当时killq老师也推荐了一本,只是他的那本太厚一直也没看过。老师推荐的30分钟第2天学完了,那也是我在网上搜集视频勉强学会正则后也是迄今为止算是唯一的一次提升,此后再无进步。
比如,“|” 这个分枝条件,我原来一直的理解是,或的关系,或左/或右,满足条件都会匹配,但是在这个坛子里记不得看过哪个帖子里说是优先匹配,一边匹配成功则另一边就会被抛弃。——所以,我其实现在连这个|的确切用法都没搞懂。
另外还有老师发的一个帖子,关于$2回调的,我都没看懂……我甚至觉得他既然用了 Evaluate函数 后面还要搞那么麻烦?
再然后就是这个竞赛题了,在此之前我压根没想过也没试过也没见过捕获分组和零宽断言可以嵌套。

知识面的欠缺不是短期内随随便便可以弥补的,
所谓的参与不过是找点题做跟着各位老师提高一下,因为我自己的工作中几乎用不上VBA,用得上的我自学第一天就解决了

TA的精华主题

TA的得分主题

发表于 2019-12-12 17:12 | 显示全部楼层
另外,咳咳,本人自学VBA才半年,所以,各位老师要加油哟,我偷师的速度可是很快的,小心一不留神被我超了  

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-12-13 17:32 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 ggmmlol 于 2019-12-16 14:17 编辑
月关 发表于 2019-12-12 17:06
非也非也。
水平不到家,我乱七八糟拼凑学来的正则本就粗糙,这点自知之明还是有的。
这句可不是什么瞎 ...

关于分支运算符"|",有一个原则的说法,就是“尽量少用、能不用则不用”,因为它可能产生回溯,导致降低效率;
同理,“零宽断言”的表达式,更是必然产生回溯,也应遵循这种“尽量少用”的原则。

本题参考答案中的正则表达式第1式,它的第一个捕获分组中的"|"运算符,也可以遵循这个原则而省略掉,就写成以下表达式:
((?:[^\de]|^)e+[\d\D]+?)?(e(?=e*\d)|$)

对应的基本结构形式就是:
(eXp1[\d\D]+?)?(eXp0|$)

经过ykqrs兄的提醒,以上表达式不正确。按参考答案剖析的结果,第1个分组应是“干扰项”和“未定项”的任意组合,而上式把它简化为1次或0次的形式,当“干扰项”连续出现2次以上时,就会有一些“干扰项”不能被充分匹配排除,这些未被排除的“干扰项”之中的符合“基本项”要求的字符也会被匹配成“目标字符”而被错误的替换掉。

看来,要简化掉干扰项eXp1与未定项'[\d\D]*?'之间的分支运算符"|",最大程度的简化也只能如参考答案的第3式'((?:(?:[^\de]|^)e+[\d\D]*?)*)(e(?=e*\d)|$)'那样,仍然必须保持组合次数为'*'而不能降为'?'

正确简化后的基本形式是:
((?:eXp1[\d\D]*?)*)(eXp0|$)
这个基本结构形式,比原来的那个要略微简单一些,因为在它的第1个捕获分组中,只是一个顺序匹配的结构。




评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2019-12-16 12:57 | 显示全部楼层
前段时间非常忙,在两天前抽出点时间上来看了看,没有时间研究,今天仔细看了一下,的确如aoe1981老师所言,这的确是正则的进阶教材,突破了逆序(肯定|否定)环视,令我受益匪浅!!!

TA的精华主题

TA的得分主题

发表于 2019-12-16 13:04 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
ggmmlol 发表于 2019-12-13 17:32
关于分支运算符"|",有一个原则的说法,就是“尽量少用、能不用则不用”,因为它可能产生回溯,导致降低 ...

((?:[^\de]|^)e+[\d\D]+?)?(e(?=e*\d)|$)
这个表达式有问题
请测试如下字符串:
beeefeee9ee4

TA的精华主题

TA的得分主题

 楼主| 发表于 2019-12-16 14:25 | 显示全部楼层
ykqrs 发表于 2019-12-16 13:04
((?:[^\de]|^)e+[\d\D]+?)?(e(?=e*\d)|$)
这个表达式有问题
请测试如下字符串:

谢谢指正。
看来,最大简化程度,也只能如参考答案的第3式那样,仅去掉第1个捕获分组中eXp1和[\d\D]*?之间的运算符分支运算符'|',而不能把它们组合的次数的限定符从'*'降为'?'

为避免误导,对原楼层的陈述已经做了更正。

TA的精华主题

TA的得分主题

发表于 2019-12-16 17:50 | 显示全部楼层
'我试着解读一下式三,不正确不足之处请ggmmlol老师指正。
reg.Pattern = "((?:(?:[^\de]|^)e+[\d\D]*?)*)(e(?=e*\d)|$)"
不是数字和字母e的单个字符或者字符串开头位置,后面紧跟单个和多个e,加0至多个任意字符,优先匹配0个,所组成的字符串,暂时把这个字符串称为x。
即(?:(?:[^\de]|^)e+[\d\D]*?)=x
(?:(?:[^\de]|^)e+[\d\D]*?)*=x*
x*就是这个叫做x的字符串匹配0次及多次,优先匹配多次。
(x*)称为第一个捕获组。
第一个捕获组加第二个捕获组即符合条件的字母e组成整个符合条件的字符串。
以eedeegr12345ee56789fgh234eee6789kse213eee123这个目标字符串为例
1、符合字符串开始位置后紧跟e,匹配ee. 紧接着匹配0个或者多个任意字符,此处优先匹配0个,此时单个x已匹配成功,因为x*,优先匹配多次,继续往右dee成功,然后依次检索直至5e. 5ee5不符合x,却符合捕获组2,从ee至5e整个字符串匹配成功,dee至5e之间用. *?匹配。
2、因为reg.Global = True,所以继续检索,从e5的e开始,x没有符合的,e5的e却符合第二组,此时匹配字符串“””e
3、继续e5的5开始,直至4e,没有复合x的字符串,4ee6的e符合第二组,空e
4、空e
5、继续,se符合第一组加任意字符至3eee1的3e,此时匹配字串se213e
6、7、与3、4匹配过程相同。
8、继续从最后的123开始搜索,没有符合第一组的,虽然没有符合第二组的e,但却有一个符合第二组的分支结构的结尾,匹配成功,空

TA的精华主题

TA的得分主题

发表于 2020-1-9 22:53 | 显示全部楼层
一开始看到这个题目就知道一定要用正则解答,但自己正则水平不行,所以就没参与
其实,说了这么多的限制条件,目的都是往正则上引导,不如直接说必须用正则解答这样来的简单明了,别人也不会费力往别的方面考虑了,直接从正则的角度去思考

TA的精华主题

TA的得分主题

发表于 2023-5-13 17:13 | 显示全部楼层
我只会用函数解,超长火车
  1. =LET(x,A2,_a,MID(x,SEQUENCE(LEN(x)),1),_b,N(_a="e"),_c,SCAN(,_b,LAMBDA(x,y,IF(y=1,x+y,y))),_d,IF(_c=0,_a,_a&"-"&_c),_e,VSTACK(DROP(REDUCE(0,SEQUENCE(ROWS(_d)-1),LAMBDA(x,y,LET(_e1,INDEX(_d,y),_f,INDEX(_d,y+1),IF(AND(LEN(_e1)=3,LEN(_f)=3),VSTACK(x),VSTACK(x,_e1))))),1),TAKE(_d,-1)),_g,VSTACK(DROP(REDUCE("a",DROP(_e,-1),LAMBDA(x,y,IF(AND(ISNUMBER(FIND("e",y)),ISNUMBER(--TAKE(x,-1))),VSTACK(x,2&"-"&TEXTAFTER(y,"-")),IF(AND(ISNUMBER(--y)*1=0,ISNUMBER(FIND("-",TAKE(x,-1)))),VSTACK(DROP(x,-1),"e"&"-"&TEXTAFTER(TAKE(x,-1),"-"),y),VSTACK(x,y))))),1),TAKE(_e,-1)),_h,DROP(REDUCE(0,_g,LAMBDA(x,y,VSTACK(x,IF(LEN(y)>1,LET(_a,TEXTSPLIT(y,"-"),_b,T(ROW(INDIRECT("1:"&@TAKE(_a,,-1)))),_b&@_a),y)))),1),CONCAT(_h))
复制代码

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?免费注册

x

TA的精华主题

TA的得分主题

发表于 2023-5-30 10:43 | 显示全部楼层
学习下,受益匪浅。觉得((^\D+)?(\d+|e*[^e\d]+e*|.*?)+)(e(?=e*\d)|$)这样,速度可能更快点。
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

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

GMT+8, 2024-12-24 04:14 , Processed in 0.036816 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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