今天看了一个设计文档,是关于怎么设计一个数据库表来模拟配置环境的,觉得设计的挺好的,估计能和数据库原理那本书对上。看了一天,头有点大,回家前写篇Perl学习笔记吧,就当翻译作业好了。Todd在公司Wiki上建了一个Page,里面有他写的一些很实用的脚本,以后再学。
目的 :匹配数字(Numeric),可以是整型,可以是浮点,可以是科学计数,有可能带正负号。
我先摘录一下整体思路,这个思路不限于匹配数字,这是一个构建正则 表达式的通用思路:
其实很多东西都是相通的,所以要多学涉猎一些学科。上面提出来的5个步骤在算法导论中也提到过,这就是典型的Divide and Conquer的思路。或许现实生活中碰到的很多问题也是这样的思路呢。好了,不说废话了,我们一步步来:
Step1:在目的里面已经比较详细了,再补充一点,我们还可以换一个角度考虑,有时候不能正面表述一个事物的时候可以用反面来描述,比如,匹配数字就意味着不能匹配字符串!
Step2:子问题再目的中也给的比较明确,一共就两类,整数和浮点数,每一类都有可能是使用科学计数法的,有可能是带正负号的。而且正负号一定出现在开头/^/,而指数部分一定出现在结尾/$/。
Step3:正负号是可选的,所以是/[+-]?/。整数的表达是/d+/。小数比较复杂,有3种形式,比如12., .12, 1.2 。对应这3种情况,分别写出正则表达式: /d+./, /.d+/和/d+.d+/。所以对于无指数部分的浮点数表达就是:
/[+-]?(d+.| .d+| d+.d+)/ ,我们来试验一下下:perl -e ‘print $1 if 123.45=~/[+-]?(d+.| .d+| d+.d+)/’;我们希望匹配123.45,可是结果是匹配123. !!为什么呢,问题出在匹配的时候,有多条道路选择的时候,从左边开始走,只要走通,就不去尝试其他的选择了。因为123.已经匹配了,所以就不去看下面的了,就错了!在使用’|'操作时一定要小心,尽量把条件更严格(更精确匹配)的表达式放在前面。这里我们必须把/d+.d+/放在/d+./的前面。
-bash-3.00$ perl -e ‘print $1 if 123.45=~/[+-]?(d+.d+|d+.|.d+)/’
123.45
现在就剩下指数部分了,/([eE][+-]?d+)?/,注意指数也是有正负的哦,而且指数部分是可选的!
Step4:从逻辑上讲,这道题目可以表达成 /^(optional sign)(integer|f.p. mantissa)(optional exponent)$/;所以最后的正则表达式就是:
/^[+-]?(d+.d+|d+.|.d+|d+)([eE][+-]?d+)?$/
Step5:这里倒没有什么优化的地方,有一点提一下,一定要写注释,不然过几天,自己都看不懂了-:)