在解决问题之前,我们需要了解一些关于‘零宽断言’特性
        ⑴ 断言(锚点也一样)和一般的正则表达式符号不同,它不匹配实际的任何字符,而是寻找文本的中的位置,是0长度。
                他们匹配的是字符之前或之后的位置。如$并不是匹配换行符,而是匹配目标字符串的末尾或整个字符串末尾的换行符之前的位置
                (?=pattern), (?<=pattern), (?!Pattern), (?<!pattern) ^, $, \b, \A, \Z 都是这样的只找‘位置’的元字符
        
        ⑵ 对于断言来说,明白两个重要概念:‘当前位置’和‘不消耗字符’,非常重要两条,如(?<=Auto)(?=It)和(?=It)(?<=Auto)是等价的,你能解释吗?
                $sResA = StringRegExpReplace("AutoIt", "(?<=Auto)(?=It)", "'")
                $sResB = StringRegExpReplace("AutoIt", "(?=It)(?<=Auto)", "'")
                你打印下会发现,$sResA和$sResB的结果是一样。若你能解释为什么一样的,说明你理解所谓的‘断言’已经有一定深度了。
                (?<=Auto)表示当前位置的左边是‘Auto’,而(?=It)表示当前位置右边是‘It',也就是只要是断言,匹配了断言的子表达式之后的‘当前位置’
                跟匹配之前的‘当前位置’是同一个位置,这也就是当引擎匹配完断言的子表达式之后,不会消耗掉如上面‘It’两个字符的,
                下一次匹配还是这Auto的o后面开始。
                这也是为什么象表达式:foo(?=bar)bee 无论匹配什么字串,它的结果永远为空的原因,因为无论在断言子表达式匹配前还是匹配后,
                引擎的当前查找位置都在foo后面,这时已经匹配了bar了,而该表达式又想在foo后面匹配bee,那就不可能了。此时到可以这样匹配
                foo(?=bar)bar,虽然可以匹配,但不过是画蛇添足而已

好了,理解了上面基础的两点,我们就可以来做这道题了

① 第一步,我们先来个稍简单的,让:
   $sStr = "1234567890"    也就是字符串只有一个纯多位数字
   这个问题核心就是从数字的最后开始三位三位地数,然后添加逗号,也就是逆序(从右到左),最容易想到的当然是逆序断言了(方向一至嘛)
   于是就有两个思路,一则就是纯只找符合要求的位置,二则就是找符合要求的数字后面,先看第一个思路:
   那么从末尾向右数3位3位地数,用正则很容易想到: ((\d{3})+$), 用$来定位串末尾的位置;再考虑不能在第一位数字前给加上逗号了,于是我们用
   逆序肯定断言 (?<=\d) 来保证(这个表达式的意思就是要找的‘位置’前面不能是数字),这个也容易。因为这里是用的纯找位置的方法,而表达式 
   ((\d{3})+$) 在匹配时是要消耗字符的,跟思路不合,于是限定一下,马上想到用顺序肯定断言来限制,((\d{3})+$)于是就变成了 (?=((\d{3})+$))
   现在把二者联系起来,不就可以了

  1. $sStr  =  "1234567890"
  2. $sRes  =  StringRegExpReplace ( $sStr ,  "(?<=\d)(?=(\d{3})+$)" ,  "," ) #左边是数字,右边以3个数字结尾分断开
  3. MsgBox ( 0 ,  "Result" ,  $sRes )

复制代码  高亮切换

上面代码已经达成简化过的目标了,我们再深入一下,去掉那个$,表达式成为 (?<=\d)(?=(\d{3})+),结果却成为了 $sStr = "1,2,3,4,5,6,7,890"
        试想一下为什么?这就想从你上面帖子所说的正则引擎如何工作的入手了,不然很难想象为什么会如此结果。我们来解析一下引擎的工作原理:
        第一次匹配:当前搜索位置在1的前面,也就是元字符'^'代表的位置,引擎解析(?<=\d)后发现1前面没有数字,于是这次匹配失败。于是引擎把‘当前位置’移一个字符到达1和2之间
        第二次匹配:引擎从‘当前位置’解析 (?<=\d),发现前面是1,符合“这个位置前面必须是数字”的要求,于是再解析 (?=(\d{3})+)
                        三位三位往后搜有 234 567 890,符合此表达式,于是在1和2之间加上‘,’,匹配完这次后,当前搜索位置再向右移动一个字符,也就是到了2和3之间
        第三次匹配:引擎从‘当前位置’解析 (?<=\d),发现前面是2,符合“这个位置前面必须是数字”的要求,于是再解析 (?=(\d{3})+)
                        三位三位往后搜有 345 678,也符合此表达式(这里虽然90不合要求,但前面已经搜出两组,满足'+'元字符要求的),所以在2和3之间加上逗号
        第四次匹配:以及后的匹配,就跟第三次一样类推了。
        所以表达式里的$保证了字符串以3的倍数位数数字结尾,这很重要!
        
        再来考虑下别的,若把里面的'+'换成 '*'会怎么样,结果是:$sRes = "1,234,567,890,",也就是0后面多了个逗号,怎么来的呢?
        我们自然想到'+'跟'*'的区别,因为后者也可以是零次重复,当引擎的当前位置是0之后时,还会匹配最后一次,此时当然这个‘当前位置’前面是数字0,满足
        (?<=\d),而后面是空位,当'*'取零次时也满足 (?<=\d)(?=(\d{3})*$),于是0后面逗号也就加上了。

② 第二步,来看看复杂点情况,也就是你给的:$sStr = "first1234567890back987654321end"
        这时,我们不能再用'$'来确定最后数字的边界了,仔细想想跟上面的有什么不同呢?不同就在于最后数字0后面不再是串结尾位置,而是任意字符了。
        当然这个‘任意’不能是数字,也就是如何找到:后面字符不是数字的位置,这不简单嘛,用顺序否定断言嘛,于是用(?!\d)替换'$',就可以得到答案了:
        (考虑下,我们这里为什么不用'\D'来替换'$',它也表示非数字呀)

  1. $sStr  =  "first1234567890back987654321end"
  2. $sRes  =  StringRegExpReplace ( $sStr ,  "(?=\d)(?=(\d{3})+(?!\d))" ,  "," )#右边是数字,右边三个数字的组,最后不是数字
  3. MsgBox ( 0 ,  "Result" ,  $sRes )

复制代码  高亮切换

看上面的代码,已经基本满足要求了,但仔细一看,居然在k和9之间也插入了一个逗号。若你把这多余的逗号倒底是怎么来的考虑明白了,
        基本上你对什么是零宽断言和引擎工作原理已经登堂入室了。留给你自己考虑,希望能发帖回复这个是啥原因?对比下面更精确的表达式

  1. $sStr  =  "first1234567890back987654321end"
  2. $sRes  =  StringRegExpReplace ( $sStr ,  "(?=\d)(\d)(?=(\d\d\d)+(?!\d))" ,  "$1," ) #右边是数字,走一个数字后,右边三个数字为组,最后不是数字
  3. MsgBox ( 0 ,  "Result" ,  $sRes )

复制代码  高亮切换

正则将长数字转为英式写法(从后向前3个数字一个逗号)相关推荐

  1. mysql数字格式化千分号的问题,即每三位一个逗号

    当需要格式话数字时,通常有如下两种中做法: 1.SELECT FORMAT(100000.7777,2); 结果: 2.SELECT CONVERT(10000.7777,decimal(12,2)) ...

  2. db2 日期英式写法_英文日期写法 英文日期格式正确写法

    在英语的作文考试中,我们会接触到一种新的题材形式,那就是书信,书信写作的好坏会直接关系到阅读者的理解,英语书信的写作中,千万不要犯一些格式类的基本错误,能避免的尽量避免掉以免影响自己的成绩,英文日期格 ...

  3. Java千问:Java语言各种数字的“非常规”写法你都会吗?

    Java程序中总是会出现一些数字.我们通常都是用常规的方式来表示这些数字,如以下代码所示 int a = 1;double b = 1.5; 但是数字也可以有非常规写法,在这里我们用一篇短文简单总结一 ...

  4. endnote修改正文中参考文献标注_请问endnote里,如何把正文中插入参考文献处的格式由数字转为(作者,年份)?感恩!...

    1.如图示操作,首先在Word的Endnote插件中将style更改为Auther-Date 2.之后点击Update Citations and Bibliography即可将数字转为"作 ...

  5. js 数字转为罗马数字(互转换),I 、II 、 III 、IV、V

    代码: //数字转为阿拉伯数字 export function intToRoman(num) {let map = {1: 'I',5: 'V',10: 'X',50: 'L',100: 'C',5 ...

  6. Excel:如何批量将文本数字转为数值型数据

    将文本数字转为数值型数据就是:将单元格里的000231转为231形式.前者是文本形式,后者是数值形式. 单个逐个点击单元格旁边的 报错号,逐个转换太麻烦了. 选择需要转换的某列,选择"数据& ...

  7. excel将常规数字转为日期格式

    如何在excel将常规数字转为日期格式?? 将如下格式的数字转为日期格式 在[开始]位置设置了[日期]格式以后,所有数据成为了#### 在[数据]-[分列]下面: 根据分列向导,第一步.第二步选择默认 ...

  8. PHP中数字转为百分位,千分位,万分位。。。

    今天做项目中,需要将文章点击量显示在页面中,需求中给的是多少多少万,虽然不是什么难事,但做程序员这么久了,需要考虑的不再是简单的实现,而且有效率和快捷, 虽然PHP自带的函数有number_forma ...

  9. Excel如何快速录入数字转为大写金额公式

    今天跟大家分享一下Excel如何快速录入数字转为大写金额公式 1.如下图我们想要将数字转为大写金额 2.首先我们选中E2单元格 3.然后点击公式向导 4.依次点击[数学统计].[人民币小写金额转大写] ...

最新文章

  1. 完美解决Error:Execution failed for task ':APP:transformClassesWithDexForDebug'...问题
  2. Cloud for Customer UI checkbox控件在PC和mobile端的不同显示
  3. linux自带磁盘加密工具下载,TrueCrypt(磁盘加密工具)
  4. 重启openstack服务_如何“ Kubernetize” OpenStack服务
  5. 智能会议系统(14)---Linphone探索:1 . Linphone官方源码探究
  6. Linux版Silverlight - Moonlight宣布停止更新
  7. 《Java 就业培训教程》
  8. 微信机器人框架【Python】
  9. Mybatis框架Mybatis下载步骤
  10. java web 页面布局框架_jsp框架(jsp实现页面框架布局)
  11. 批量删除文件到回收站
  12. 基于uni-app的模板,支持h5,小程序,安卓,ios,request请求封装,全局路由拦截,也可作为项目基础模板使用
  13. wamp中php无法启动,wamp无法正常启动
  14. ENVI5.3.1 去除影像四周的黑色背景
  15. 电路杂谈——硬件经典面试题
  16. 【Al TIME】博硕论坛064期 | 清华计算机系大佬齐论Al
  17. 可以免费下载视频素材和模板网站汇总
  18. 利用python和Sen2cor对Sentinel2进行批量大气校正
  19. 起用 RabbitMQ (二)
  20. win10系统升级没有声音?老司机教你怎么重新安装声卡驱动

热门文章

  1. ubuntu 14.04 wifi peap 选择证书问题
  2. 如果你画了一个圆被挤扁了
  3. 【综合评价方法 熵权法】指标权重确定方法之熵权法
  4. 《袁老师访谈录》第十一期|宗福季教授/香港科大(广州)信息枢纽署理院长【问诊未来·院长系列:拥抱数字化转型】...
  5. 钟汉良日记:改变心态了,回武平待3年
  6. 欢迎各位小伙伴来领取免费的安卓教程
  7. 投基取巧:如何通过基金投资获得 20%+ 的收益?基金理财干货分享,附思维导图!
  8. 同时使用网线以及无线上网
  9. ES6-11数值扩展:二进制和八进制、数值分隔符、Number.isFinite()、Number.isNaN()等
  10. 2023 《电脑PC游戏》 红警3:起义时刻