精通正则表达式:第二章(1)
精通正则表达式:第二章本文关注的是正则表达式,只是因为Perl对正则表达式的支持优于其他语言,所以选用Perl,请不要过多的关心Perl是怎么回事,必要的前置知识会在这里提及。下面开始我们的正则之旅。在本文,会使用 · 来代替正则表达式中出现的空格。 一、简单易懂的Perl魔法下面是一段简单的Perl示例程序,功能是将华氏温度转换为摄氏温度。 $celsius = 30; $fahrenheit = ($celsius * 9 / 5) + 32; #计算华氏温度 print "$celsius C is $fahrenheit F.n" #输出两种温度 其结果为: 30 C is 86 F. 从这段程序中,我们会发现Perl的几个特点:
同时,Perl也提供了流程控制语句,如while: $celsius = 20; while ($celsius <= 45) { $fahrenheit = ($celsius * 9 / 5) + 32; print "$celsius C is $ fahrenheit F.n"; $celsius = $celsius + 5; } 运行结果如下: 20 C is 68 F. 25 C is 77 F. 30 C is 86 F. 35 C is 95 F. 40 C is 104 F. 45 C is 113 F. 当条件为真的时候,while循环控制的部分就会重复执行,直到条件为假。如果在终端中运行,则就像下面这样: /~> perl -w CelToFah.pl 这里的 二、匹配文本在Perl中,最简单的正则表达式使用方法就是:检查变量中的文本是否能匹配指定正则表达式。实例片段如下: if ($reply =~ m/^[0-9]+$/){ print "only digitsn"; } else { print "not only digitsn"; } 如你所见,第一行的表达式颇有魔法风范:正则表达式是 需要注意的是, $reply =~ m/^[0-9]+$/ 的返回值取决于变量reply。如果其内容能匹配正则表达式 首先,会提示用户输入一个值,接受这个输入并用正则表达式去验证:如果输入的是数值,则计算相应的华氏温度;否则报错。实例如下: print "Enter a temperature in Celsius:n"; $celsius = <STDIN>; #从用户处接受一个输入 chomp($celsius); #去掉换行符 if ( $celsius =~ m/^[0-9]+$/) { $fahrenheit = ($celsius * 9 / 5) + 32; #计算华氏温度 print "$celsius C is $fahrenheit Fn"; } else { print "Expecting a number,so I don't understand "$celsius".n"; } 字符里面的转义就不再赘述了。要注意的是,Perl中,字符串和正则表达式的区别既不明显,也不重要,这是它和其他语言的一大区别。运行结果如下: Enter a temperature in Celsius: 123 123 C is 253.4 F 该版本的Perl浮点数处理的很好……那我就不黑了。 更进一步我们可以拓展这个例子,使它支持小数和负数。计算部分就交给Perl吧。负数就是一个可选的负号,而小数则是可选的小数点和任意数字。所以拓展后的正则表达式是这样的: m/^-?[0-9]+(.[0-9]*)?$/ 现在,他就可以匹配-19、0.343这类的数字了,但是.9834这种数字还是无法匹配,由于不是什么大问题,我们会留到很后面再来处理。 成功匹配的副作用现在,我们除了要匹配数字,还要用户可以输入C和F来标识输入的温度类型,并进行转换。 m/^([-+]?[0-9]+)([CF])$/ 在这个表达式中,使用括号围住了“有价值”的部分,捕捉过后,我们可以决定要使用它们来做什么。现在,我们打算实现之前提到的事情:匹配数字,还要用户可以输入C和F来标识输入的温度类型,并进行转换。 print "Enter a temperature in Celsius:n"; $input = <STDIN>; #从用户处接受一个输入 chomp($input); #去掉换行符 if ( $input =~ m/^([-+]?[0-9]+)([CF])$/) { #程序运行到这里就已经匹配好了。$1保存数字,$2保存符号。 $InputNum = $1; $type = $2; if ($type eq "C") { #输入为摄氏温度,计算华氏温度 $celsius = $InputNum; $fahrenheit = ($celsius * 9 / 5) + 32; } else { #否则,应该是"F",那就计算摄氏温度。 $fahrenheit = $InputNum; $celsius = ($fahrenheit - 32) *5 /9; } #现在得到两个温度值,显示结果,并使用格式化字符串。 printf "%.2f C is %.2f F.n",$celsius,$fahrenheit ; } else{ #如果一开始没有匹配,则报错。 print "Expecting a number followed by "C" or "F",n"; print "So I don't understand "$input".n"; } 结果如下: PS E:LearnPerl> perl -w .REdigits1.pl Enter a temperature in Celsius: 22F -5.56 C is 22.00 F. PS E:LearnPerl> perl -w .REdigits1.pl Enter a temperature in Celsius: 39C 39.00 C is 102.20 F. PS E:LearnPerl> perl -w .REdigits1.pl Enter a temperature in Celsius: oops Expecting a number followed by "C" or "F",So I don't understand "oops". 但这里离成功还有一定距离,比如:
为了赶上这些距离,我们还有几件事情要做。首先,我们向正则表达式添加小数部分的匹配。修改如下: Enter a temperature in Celsius: 11.2F type is .2 InputNum is 11.2 可以明显的看到,$1匹配的整个数字,也就是外围的第一个括号分组
现在,我们可以来处理空格了。我们可以使用 Enter a temperature in Celsius: 33.98 c 1.10 C is 33.98 F. 结果不尽如人意……嗯,再修改一下即可。 print "Enter a temperature in Celsius:n"; $input = <STDIN>; #从用户处接受一个输入 chomp($input); #去掉换行符 if ( $input =~ m/^([-+]?[0-9]+(?:.[0-9]*)?)s*([CF])$/i) { #程序运行到这里就已经匹配好了。$1保存数字,$2保存符号。 $InputNum = $1; $type = $2; if ($type =~ m/c/i) { #输入为摄氏温度,计算华氏温度 $celsius = $InputNum; $fahrenheit = ($celsius * 9 / 5) + 32; } else { #否则,应该是"F",那就计算摄氏温度。 $fahrenheit = $InputNum; $celsius = ($fahrenheit - 32) *5 /9; } #现在得到两个温度值,显式结果。 printf "%.2f C is %.2f F.n",n"; print "So I don't understand "$input".n"; } 到这里就先休息下吧。顺便来道题目思考思考:
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |