找回密码
 加入
搜索
查看: 4556|回复: 9

[AU3基础] 很难的一个正则:匹配所有格式正确的整数和小数

  [复制链接]
发表于 2013-2-12 14:02:42 | 显示全部楼层 |阅读模式
如下面这些格式都是正确的:
123   +25   89   12.3   +4.12   -78.32   +.23   .101   -.52
(财务上就经常有“+.23   .101   -.52”样的数字)

但不能匹配ip地址样的数字(如:192.168.0.1),日期样的数字(如:2013.02.11)
怎么写?


#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($sStr, '_____________________', 3) ;这个空该如何写?
_ArrayDisplay($aRes)
发表于 2013-2-12 18:10:46 | 显示全部楼层
(?<=^|[^\.\d])([+-]?(?:\d*\.)?\d+)(?=[^\.\d]|$)
试下

评分

参与人数 1金钱 +20 收起 理由
runsnake + 20 谢谢了

查看全部评分

发表于 2013-2-12 19:50:14 | 显示全部楼层
本帖最后由 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代码,却能做绝大多数的正则问题,你看了它的代码就知道,里面解析正则全是迭代。

评分

参与人数 2金钱 +50 贡献 +2 收起 理由
runsnake + 20 非常感谢
xms77 + 30 + 2 听君一席话,胜读十年书!

查看全部评分

发表于 2013-2-12 21:41:24 | 显示全部楼层
本帖最后由 shqf 于 2013-2-12 21:49 编辑

我也来练习一下:
(?<=^| )([+-]?\d*\.?\d+)(?= |$)

评分

参与人数 1金钱 +20 收起 理由
runsnake + 20 不错

查看全部评分

发表于 2013-2-13 09:52:56 | 显示全部楼层
对于正则,我都是慢慢调试~
发表于 2013-2-13 10:37:17 | 显示全部楼层
回复 3# happytc
以前考虑正则都是想着一个正则表达式来解决,现在想来真的是钻牛角尖了,原来复杂的问题分段来解决要简单直观一点。
对于我这个编程门外汉来说,没有能力考虑程序的效率问题,只要能够解决问题就好了。
听君一席话,胜读十年书!
发表于 2013-2-13 12:15:25 | 显示全部楼层
真是艰深 复杂 小弟叩拜各位大侠来了
 楼主| 发表于 2013-2-15 09:23:34 | 显示全部楼层
多谢h大侠教导
我也是老想着一个正则解决所有问题
原来还有这么多‘道道’在里面
学习了,真是那种:听君一席话,胜读十年书的感觉
发表于 2013-2-17 11:47:26 | 显示全部楼层
谁能把那个正则用语言讲清楚!
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-9-29 09:27 , Processed in 0.110230 second(s), 25 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

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