本帖最后由 happytc 于 2013-2-12 19:56 编辑
回复 1# runsnake
嗯,上次你问的关于‘数字里加逗号’的正则问题,我给你长篇讲了半天断言
看来你还是不能活用呀。建议你再回去读一下,其实你原来问的那个正则和你现在问的问题,本质上是一类问题!
其实,话又说回来了,个人觉得用正则,并不要那种一个正则解决全部问题,要在“效率、可读性、思考时间”之间找到平衡。并不是说写在一个正则里,效果就高,就优美。
就如你这个问题,与其想半天都想不出来,远不如来个两步,先过虑掉ip和日期格式的数据,这样使问题一下就简单多了,多来一步,又不丢人。很多时候,远比那些复杂的正则效率高,因为一般复杂的表达式都要经过很多次回溯。
你给的数字,一看就很容易想到分成两类数据,一类是普通数,一类就是你一楼所说的‘财务上用到的特别形式’,叫我做,才懒得想高级的:直接第一步过滤掉非正确数字;第二步用两个分支匹配两类数:
#include <Array.au3>
$sStr = '123 +25 89 192.168.0.1 2013.02.11 12.3 +4.12 -78.32 +.23 .101 -.52'
$aRes = StringRegExp(StringRegExpReplace($sStr, '(\d+\.){2,}\d+', ''), '[+-]?\d+(?:\.\d+)?[^.\d]|[+-]?\.\d+', 3)
_ArrayDisplay($aRes)
你前面的那个正则问题:http://www.autoitx.com/forum.php ... 7212&highlight=
也是这样,与其打破脑袋想,远不如搞个循环解决问题:
$sStr = "first1234567890back987654321end"
While StringRegExp($sStr, '(\d)((\d\d\d)+(?!\d))')
$sStr = StringRegExpReplace($sStr, '(\d)((\d\d\d)+(?!\d))', '$1,$2')
WEnd
MsgBox(0, 'Result', $sStr)
另外,其实一楼的你这个新问题,同样可以用循环解决的。或者说,零宽度断言的东西,因它不消耗字符,有时我们的需要却是:既需要找到某些字符串来定位,但又需要‘消耗’字符,这时完全可以用迭代或循环/迭代来达到消耗字符的目的。换句话说:零宽度断言完全可以用迭代或循环模拟。其实引擎内部在解析零宽度断言时的算法,就是用迭代或循环的。你直接用,相当于少了引擎解析零宽度断言,效率更高。
不知道你能不能写出这个问题的循环解决法来:参照我上面给你写的旧问题思路和kevinch高手给你这个问题写的用零宽度断言的例子。
想想grep工具,才500来行的c代码,却能做绝大多数的正则问题,你看了它的代码就知道,里面解析正则全是迭代。 |