ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[原创] 提取符合特定规则的文本,我用“万能正则表达式”!

  [复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-8-18 15:03 | 显示全部楼层
fsq119 发表于 2018-8-18 13:21
借用楼主的Evaluate方法:
a = Evaluate(Chr(34) & REGREPLACE(s, "(\d)((e)+)(?=\d)", "$1"" & len(""$ ...

感谢你代我回答了30楼的提问。

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-8-18 15:45 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
fsq119 发表于 2018-8-18 13:21
借用楼主的Evaluate方法:
a = Evaluate(Chr(34) & REGREPLACE(s, "(\d)((e)+)(?=\d)", "$1"" & len(""$ ...

你的这一条其实还可以简化。
因为你这个表达式中的第3个捕获分组匹配到的将是一个常量:单字母e

或者说,原来的正则表达式"(\d)(e+)(?=\d)"仍然有效。只是REGREPLACE函数的第3参数,修改一下,就可以满足30楼的提问。

TA的精华主题

TA的得分主题

发表于 2018-8-18 18:26 | 显示全部楼层
已经这么多楼层了,楼主能否用你的万能表达式举两个“提取”的例子,看看你的替换函数是怎么用的??

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-8-18 18:53 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
fsq119 发表于 2018-8-18 18:26
已经这么多楼层了,楼主能否用你的万能表达式举两个“提取”的例子,看看你的替换函数是怎么用的??

好的,我正在做一个示例,不过,录制制作过程虽简单,但要讲解其中的解题思路,并用文字语言准确表达出来,反而是较考究的事情。所以,可能要稍晚些才能贴出来了。

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-8-18 19:49 | 显示全部楼层
本帖最后由 ggmmlol 于 2018-8-18 19:57 编辑

对于正则表达式对象的Replace方法来说,对目标内容做正则替代,是它的本行工作,无需多做讲解。
故本例 只演示用正则表达式Replace方法对目标内容做正向提取的过程。即按下面的方法二的解题思路处理


问题描述:如下图所示
在工作表E列的销售明细中,同一单元格中记录了多个日期各自对应的销售金额
现在,想对同一个单元格中提取多个金额进行求和,列出在F列同一行的单元格中。
捕获.PNG

解答:用【超级查找替换】加载宏小工具
方法一查找:(\d+-\d+|\D+)+
替换为:+
解题思路:把不需要的内容(本例中为:日期和非数字)替换为分隔符:+
方法二查找:[\s\S]*?(?:\d+-\d+\D+)(\d+)|[\s\S]+
替换为:+$1
解题思路:提取目标内容(本例中为:出现在日期后面的金额),并前缀一个分隔符+
原求助贴链接:
在同一个单元格中提取多个金额进行求和
http://club.excelhome.net/thread-1196353-1-1.html
(出处: ExcelHome技术论坛)




超级替换68.gif

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-8-18 23:59 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
第四节:实例演示 提取手机号码

实例来源:
求助:如何在字符串中提取手机号码
http://club.excelhome.net/thread-1415083-1-1.html
(出处: ExcelHome技术论坛)



1、手机号码都是11位数字,且第1位必须是1,其相匹配的正则表达式是:1\d{10}
2、如果考虑到手机号码的第2位数字不能出现0-2,则更加严格一点的表达式是1[3-9]\d{9}
3、而且手机号必须是正好11位,所以其前后都不能紧接数字,需要加上前后定位的表达式:
\D?(1[3-9]\d{9})(?!\d)

把它代入“万能表达式”:
[\s\S]*?(eXp)|[\s\S]+
得到:
[\s\S]*?\D?(1\d{10})(?!\d)|[\s\S]+

使用这个表达式提取手机号码的演示和表格附件如下

提取手机号码.rar (7.3 KB, 下载次数: 94)

超级替换63.gif










TA的精华主题

TA的得分主题

 楼主| 发表于 2018-8-19 16:39 | 显示全部楼层
本帖最后由 ggmmlol 于 2018-8-19 16:40 编辑

第五节:实例之——提取字符串中的多项金额,并计算合计金额。

本例直接从我的另一个主题引用而来。
其中的正则表达式可以由“万能正则表达式”简略写法套用得到:
.*?(\d*\.?\d+)元|.+
它匹配正或负的整数或小数型金额数值(即数值右侧紧接字符“元”的数值)的绝对值部分。
如果希望对负的金额匹配相应的负数值,则略做修改即可,如下所示:
.*?(-?\d*\.?\d+)元|.+

详细内容,请参见原贴第7楼:

[加载宏]单元格小工具之六——超级查找替换
http://club.excelhome.net/thread-1421478-1-1.html
(出处: ExcelHome技术论坛)

超级替换44.gif

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-8-19 16:46 | 显示全部楼层
本帖最后由 ggmmlol 于 2018-8-19 16:54 编辑

第六节 实例之含有注释字符的工程量计算式求值

工程量计算表是一种较特殊的工程行业表格,一般工程施工技术员、造价员、造价审计员都会用到。
它的特殊之处在于,在表格中,不仅要计算出工程量,还要明示工程量的计算过程,并且需要简明注释其中的某些数据,以便自己或他人快速核对工程量计算的准确性。这就必然导致表格中出现含有注释字符的文本算式的求值问题。
很多工程人员,通过网络搜索寻找解决办法,大多都了解到:通过在名称定义中使用Excel的宏表函数Evaluate,可以实现对文本计算式求值,但一般也会同时了解到,宏表函数Evaluate存在参数长度不能超过255个字符的限制,否则会出现错误。

那么,有没有一种简便的、而且通用的办法,把含有注释字符的计算式还原其本来面目,以便利用EXCEL的公式求值这种透明的手段来计算工程量呢?
答案是肯定的。

下面的动图演示用正则表达式的Replace方法对工程量计算式求值。
由于前面的几个例子,都是讲解用Replace的“正向提取”即利用“万能正则表达式”来得到匹配表达式eXp的字符串。
所以,这次特别选用这个实例,来讲解用Replace的“反向提取”功能。其实,这是其Replace方法的老本行:直接排除匹配于表达式eXp的字符部分,而得到期望的目标内容。

这时,万能正则表达式就从 [\s\S]*?(eXp)|[\s\S]+ 简化为(eXp),由于并不需要保留eXp所匹配的内容,连分组运算符都可去掉,彻底地简化为:
eXp
而替换成的内容,通常是替换为空,或者是替换为一个作为分隔符的字符。

本例分析:
工程量计算式中,为了区分计算式中的注释字符与正常的计算式字符,通常会把注释字符包含在成对的全角方括号或全角圆括号之中。

从以下动图中可以看出,本例就属于这种常见的注释方式,因此,匹配于需要删除的注释字符的正则表达式是:
(【.*?】|(.*?))+
直接替换为空

超级替换70.gif


本例的表格附件:
工程量计算.rar (11.22 KB, 下载次数: 113)


TA的精华主题

TA的得分主题

 楼主| 发表于 2018-8-22 11:08 | 显示全部楼层
第八节 实例之——从文本中提取所有电话号码(包括手机和座机号码)

实例来源:
[求助]提取表格里的电话号码?
http://club.excelhome.net/thread-1128457-1-1.html
(出处: ExcelHome技术论坛)

首先,分析电话号码的特征:
第一种方法:使用较严格的验证条件
其中,
1、手机号码:
  为11位数字,第1位必须是1,第2位不能是0、1、2,即必须是[3-9],剩余9位可为任意数字,\d{9},综合下来,可表示为
  1[3-9]\d{9}
2、固定电话号码:区号-本地号-分机号

  区号:
  为3位或4位的数字,后面带有“-”号,表示为:\d{3,4}-
  区号可能存在,也有可能不存在,其整体出现的次数为0至1次,
  综合:(\d{3,4}-){0,1},可简写为(\d{3,4}-)?
      
  本地号:
  为7至8位数字,表示为:\d{7,8}
  
  分机号:
  一般为4位以内的数字,前面带有“-”号,表示为:-\d{1,4}
  分机号也有可能不存在,因此就是
  (-\d{1,4})?
  3个部分,连接为整体:
  (\d{3,4}-)?\d{7,8}(-\d{1,4})?
3、把手机号和固定电话并列,两者之间需要加上竖线符号“|”,综合表示为:
  1[3-9]\d{9}|(\d{3,4}-)?\d{7,8}(-\d{1,4})?
4、电话号码的前后都必须不能紧接有其它数字,因此,上式需要外加括号作为一个整体,然后在其前面、后面都要添加“\D?”
5、最终的结果为
  \D?(1[3-9]\d{9}|(\d{3,4}-)?\d{7,8}(-\d{1,4})?)\D?
第二种,使用相对宽松的验证方法:
  手机或固话至少有一组7位以上的数字:d{7,}
  在其前后这可以各有以数字和-号组成的若干数字:前面为(d{3,4}-)?,后面为(-d{1,4})?
  综合为:
\D?((\d{3,4}-)?\d{7,}(-\d{1,4})?)\D?
第三种,使用最宽松的验证方法:
  手机或固话,都是以数字开头和结尾,且中间包含5个以上的数字或-号:
  \D?(\d[0-9-]{5,}\d)\D?
  
  
本例演示动图中,采用最为严格的验证模式,即第一种方法得到的最终表达式。
演示如下:
超级替换74.gif

评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2018-8-22 12:31 | 显示全部楼层
本帖最后由 ggmmlol 于 2018-8-22 12:39 编辑

第九节 实例之——提取符合特定条件的字符,并去掉重复项
实例来源:
[求助] 如何提取字符串中的前两个字符并去掉重复项?
http://club.excelhome.net/thread-1126765-1-1.html
(出处: ExcelHome技术论坛)

问题描述:
如何提取单元格中,每段以分号为分隔的字符串的前两个英文字符并去掉重复项
分步分析:
1、两个英文字符:([a-zA-Z]{2})
2、且定位于以分号分隔的每段中的最前位置
即:[\s\S]*?([a-zA-Z]{2})[^;]*;?|.+
3、该字符不重复,即在它之后没有相同的项,需要再加上后续定位条件:(?![\s\S]*?\1),即:
[\s\S]*?([a-zA-Z]{2})(?![\s\S]*?\1)[^;]*;?|.+
4、保留该段字符的分隔符,以作为结果项的分隔符,所以对“;?”加上捕获分组运算的括号,最终结果为:
[\s\S]*?([a-zA-Z]{2})(?![\s\S]*?\1)[^;]*(;?)|.+

演示如下:
超级替换75.gif

实例表格附件:

提取同一单元格中符合条件且不重复的字符.rar (7.95 KB, 下载次数: 130)

评分

1

查看全部评分

您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-12-23 20:02 , Processed in 0.038016 second(s), 8 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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