ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[分享] 加强版VB正则表达式(VBScript.RegExp)组件,兼容Perl正则语法

  [复制链接]

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-11-19 00:41 | 显示全部楼层
本帖已被收录到知识树中,索引项:文本处理和正则
本帖最后由 coby001 于 2014-11-19 00:44 编辑

Sub nxReg_test2()
    Dim nxReg As New NewXing.RegExp   
    Const s = "a,b,c,D,ff,       12,333,444,555.00,g,H,i" '   
    nxReg.Global = True
    nxReg.Pattern = ",(?!\d{3}\D)"  ' 按逗号分割字串,但保留 数值中的千分位逗号   
    Dim sArr$(), tmp
    sArr = nxReg.Split(s)
    For Each tmp In sArr
        Debug.Print tmp
    Next

End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-11-19 00:43 | 显示全部楼层
Sub nxReg_test3()
    Dim nxReg As New NewXing.RegExp   
    Const s = "a,b,c,D,ff,       12,333,444,555.00,g,H,i" '   
    Dim sArr$(), tmp
    sArr = nxReg.Split(s, ",(?!\d{3}\D)", "g") ' 实现相同的功能,更加简洁
    For Each tmp In sArr
        Debug.Print tmp
    Next
End Sub

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-11-19 09:50 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
由于在 正则 里说 正向/反向前/后 ,是比较容易混淆的,所以改成 左/右,这样容易理解。

Sub nxReg_test()
    Dim nxReg As New NewXing.RegExp
    Dim nxMC As NewXing.MatchCollection
    Dim nxMch As NewXing.Match
    Const s = "8 123 456 aa gg .99"
    nxReg.Global = True
    nxReg.Pattern = "(?<=\.)\d+(?#数字左边小数点)" ' 零宽断言,可以 预查
    Set nxMC = nxReg.Execute(s)
    For Each nxMch In nxMC
        Debug.Print nxMch.Value ' 只匹配 99
    Next

     ' 零宽断言,可以 预查
    For Each nxMch In nxReg.Execute(s, "(?<![.\d])\d+(?#数字左边小数点)","g")
        Debug.Print nxMch.Value ' 匹配 8,123,456 ,匹配 99
    Next

End Sub

vba的 reg5.5 没有此功能哦~

TA的精华主题

TA的得分主题

发表于 2014-11-19 10:28 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
coby001 发表于 2014-11-19 09:50
由于在 正则 里说 正向/反向 ,前/后 ,是比较容易混淆的,所以改成 左/右,这样容易理解。

Sub nxReg_t ...

确实,负向零宽断言是vbs正则的永远的痛。

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-11-19 10:36 | 显示全部楼层
wcymiss 发表于 2014-11-19 10:28
确实,负向零宽断言是vbs正则的永远的痛。

有了 左右预查,就可以实现自定义的边界符了,中文也可以找边界了~~
\b  只是针对 半角字母和数字 才有效。

TA的精华主题

TA的得分主题

发表于 2014-11-19 13:34 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2014-11-19 14:03 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
coby001 发表于 2014-11-19 10:36
有了 左右预查,就可以实现自定义的边界符了,中文也可以找边界了~~
\b  只是针对 半角字母和数字 才有效 ...

再来个递归的例子啊。

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-11-19 14:12 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
wcymiss 发表于 2014-11-19 14:03
再来个递归的例子啊。

好的,,=我有空就写一个,,,。。
现在有事要忙~

TA的精华主题

TA的得分主题

发表于 2014-11-19 15:09 | 显示全部楼层
coby001 发表于 2014-11-19 14:12
好的,,=我有空就写一个,,,。。
现在有事要忙~

如果有这样的功能我就觉得完美了~~~

Sub jsReg_test()
    '把数字部分都减去10
    Const s = "123-*-4567-s-77"
    With CreateObject("MSScriptControl.ScriptControl")
        .Language = "javascript"
        Debug.Print .Eval("('" & s & "').replace(/\d+/g,function(e){return e-10})")
        '返回113-*-4557-s-67
    End With
End Sub

对于按规则批量修改数据很有用。。

TA的精华主题

TA的得分主题

 楼主| 发表于 2014-11-19 21:13 | 显示全部楼层
wcymiss 发表于 2014-11-19 14:03
再来个递归的例子啊。

递归表达式 (?R)
对另一部分子表达式的引用,而是对其匹配结果的引用。当被引用的表达式包含自身,则形成递归引用。
说明
相对于 "反向引用" 来说,反向引用是在匹配过程中,对匹配到的字符串内容进行引用,而 "递归匹配" 是对表达式进行引用。


---------例子----------
原字串:(a * (c + 2))

目的:捕获每一对带括号的数学公式,括号要正确配对。

首先,按普通的想法就是先找到括号:
nxReg.Pattern = "\(.*\)"  ' 两边有 括号,并且它的中间有任意内容
这个模式是贪婪的,会把整个原字串都捕获了,不能正确匹配出“(c + 2)”子字串。


改进:找到括号中间没有其他括号的
nxReg.Pattern = "\([^()]*\)"  ' 两边有 括号,并且它的中间没有其他括号
这个模式能正确匹配出“(c + 2)”子字串了。


那外面还有一层括号呢,怎么写,
                          \(([^()])*\)                ' 1层
             \(([^()]|\(([^()])*\))*\)          ' 2层
\(([^()]|\(([^()]|\(([^()])*\))*\))*\)    ' 3层
………………其他的层 依次嵌套


看得出来,每次嵌套都是同一个模式的重复,就是 原模式的自身嵌套
用一个符号来表示这种递归引用自身表达式的方法:(?R)


nxReg.Pattern = "\(([^()]|(?R))*\)"

例子:
  1. Sub nxReg_test5()
  2.     Dim regex As New NewXing.RegExp
  3.     Dim matches As NewXing.MatchCollection

  4.     regex.Pattern = "\(([^()]|(?R))*\)"
  5.     regex.Global = True

  6.     Set matches = regex.Execute("(a * (c + 2))")
  7.    
  8.     Debug.Print matches(0).Value ' 外层
  9.     Debug.Print matches(0).SubMatches(0) ' 内层
  10. End Sub
复制代码




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

本版积分规则

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

GMT+8, 2024-12-4 16:46 , Processed in 0.043653 second(s), 7 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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