21.5几例常见正则表达式分析
21.5 几例常见正则表达式分析
前面4节分别讲述了正则表达式的基本概念、正则表达式常用字符分类、PHP中POSIX扩展正则表达式函数及兼容PERL的正则表达式函数。正则表达式这些看似“怪异”的语法,有时的确会让读者感到困惑,尤其对初学者来说,那类似天书一般的正则表达式代码更是让人望而却步,无所适从。
无论怎样,掌握并且熟练使用正则表达式是需要一个渐进过程的。这个过程是一个大量实践和积累的过程,需要毅力、耐力和信心。本节就通过几个完整而且具体的正则表达式实例,让读者进一步学习、理解和应用正则表达式。
21.5.1 检查IP地址的正则表达式
IP地址由句点“.”分割的几部分数字字符串组成,例如192.0.170.10。其通用形式是×××.×××.×××.×××,这里的×××是整数,范围是0~255。因此IP地址中由“.”分割的每个数字串,至少有一个数字,至多有3个数字。既然×××都是数字,那么首先考虑到的正则表达式[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}。因为[0-9]{1,3}完全可能匹配256、515和999等字符串,所以这个正则表达式并不能保证IP地址的每个数字部分都不超过255。为了便于理解,对IP地址数字部分是否超过255的判断,将通过一个简单的比较表达式来完成。代码21-13是匹配IP地址正则表达式的第1个版本程序,先看看它是否起作用。
代码21-13 检查IP地址的正则表达式(一)21-13.php
01 <?php
02 $arr_ip = array(
03 "127.0.0.1",
04 "218.206.10.123",
05 "192.221.521.0",
06 "123.0.0.0.1",
07 "-12.255.0.10",
08 "10.9c.132.69",
09 "255.10.10.255"
10 ); //
定义一个数组,包含一些IP
地址
11
12 foreach ($arr_ip as $ip) //
遍历数组中的IP
13 {
14 if(validateIp($ip)) //
验证IP
15 {
16 echo "<b>$ip
是正确的IP
地址</b>";
17 echo "<br/><br/>";
18 }
19 else
20 {
21 echo "$ip
不是正确的IP
地址";
22 echo "<br/><br/>";
23 }
24 }
25
26 function validateIp($ip) //
验证IP
的函数
27 {
28 $iparray = explode(".",$ip);
29 for($i=0;$i<count($iparray);$i++)
30 {
31 if($iparray[$i]>255)
32 return (0);
33 }
34 return ereg("[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}",$ip);
35 }
36 ?>
【代码解析】代码中将对IP地址的检查放到函数validateIp()中完成,这个函数由两部分组成,一是判断IP地址的每个数字部分是否超过255,对于每个数字部分都不超过255的表达式才做进一步判断;二是将最后的匹配由函数ereg()完成。自定义函数最后将正则表达式函数ereg()的返回值返回。执行代码21-13,可以看到如图21-15所示的结果。
从这个执行结果看到,有的IP地址得到了正确的匹配,但有些错误的IP地址也被认为是合法的IP地址了,例如123.0.0.0.1和-12.255.0.10都是不正确的IP地址格式,但在代码21-13中被认为是正确的。
这个问题就出在正则表达式上,再仔细研究一下程序中使用的正则表达式:[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3},可以看出123.0.0.0.1的一部分完全匹配这个正则表达式,例如123.0.0.0这部分就匹配程序中给定的正则表达式,所以才会出现将123.0.0.0.1认为是合法IP地址格式的问题。同样的道理,-12.255.0.10也可以匹配程序中给定的正则表达式。
知道了原因所在,就好解决这个问题。代码21-14是检查IP地址格式是否合法的第2个版本程序。
代码21-14 检查IP地址的正则表达式(二)21-14.php
01 <?php
02 $arr_ip = array(
03 "127.0.0.1",
04 "218.206.10.123",
05 "192.221.521.0",
06 "123.0.0.0.1",
07 "-12.255.0.10",
08 "10.9c.132.69",
09 "255.10.10.255"
10 ); //
定义一个数组,包含一些IP
地址
11
12 foreach ($arr_ip as $ip) //
遍历IP
数组
13 {
14 if(validateIp($ip)) //
验证IP
15 {
16 echo "<b>$ip
是正确的IP
地址</b>";
17 echo "<br/><br/>";
18 }
19 else
20 {
21 echo "$ip
不是正确的IP
地址";
22 echo "<br/><br/>";
23 }
24 }
25
26 function validateIp($ip) //
验证IP
的函数
27 {
28 $iparray = explode(".",$ip);
29 for($i=0;$i<count($iparray);$i++)
30 {
31 if($iparray[$i]>255)
32 return (0);
33 }
34 return ereg("^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$",$ip);
//
正则表达式
35 }
36 ?>
【代码解析】这段程序将原来的正则表达式改为^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$,通过在原正则表达式开头加^,结尾加$,保证了正则表达式只能匹配由.连接的4段数字字符。代码21-14的执行结果如图21-16所示。从这个执行结果可以看出,123.0.0.0.1和-12.255.0.10都被检查为错误的IP地址格式。

图21-15 检查IP地址的结果

图21-16 修正后的检查IP地址的结果
21.5.2 检查中文字符的正则表达式
中文在ASCII码中有一定的范围,这个范围是0xa1~0xff,所以可以用正则表达式0xa1-0xff来表示中文。代码21-15是检查匹配完全中文字符串的示例程序。
代码21-15 匹配中文字符串21-21.php
01 <?php
02 $str_arr = array(
03 "IAMEVERYSORRY",
04 "
快乐编程,快乐生活",
05 "PHP
编程",
06 "1997
年香港回归",
07 "
英语学习ABC",
08 "123456789"
09 ); //
定义字符串数组
10
11 $patt_ch = chr(0xa1) . "-" . chr(0xff); //
匹配中文字符的ASCII
范围
12
13 foreach ($str_arr as $str)
14 {
15 echo "
字符串"$str"
是";
16 if (preg_match("/^[$patt_ch]+$/", $str)) //
注意在正则表达式的前后使用界定符“//
”
17 {
18 echo "
完全中文";
19 echo "<br>";
20 echo "<br>";
21 }
22 else
23 {
24 echo "
非完全中文";
25 echo "<br>";
26 echo "<br>";
27 }
28 }
29 ?>
【代码解析】程序中使用了兼容PERL正则表达式函数preg_match()。代码第11行使用了函数chr(),该函数返回ASCII码所指定的单个字符。注意第16行在函数preg_match()中所使用匹配中文的模式,在这个正则表达式中加入^和$,以保证匹配完全的中文(即纯中文字符串)。这段代码的执行结果如图21-17所示。

图21-7 使用正则表达式匹配中文字符串
读者可以试着将正则表达式前后的^和$去掉看看执行结果有什么不同。
21.5.3 检查Email地址的正则表达式
本小节介绍如何使用正则表达式来检查一个Email地址的格式是否是合法。Email地址一般由如下所述3部分构成。
·用户名,即符号@左边的所有字符。
·符号@。
·服务器域名,即符号@右边的所有字符,通常这些字符应该组成一个合法的域名,如php.net等。
通常,不同的邮箱提供商对Email的用户名有不同的限制,如用户名长度不能低于6位字符,用户名只能由数字和字母组成,不能有特殊符号(如下划线_)等。本小节要完成的正则表达式,将不过多考虑这些细节,本例将假设Email用户名可以含有大小写字母、阿拉伯数字、减号(-)以及下划线(_)。域名的规则也类似,但是有英文句点(.),而没有下划线。
(1)写出Email用户名的正则表达式,根据上述分析,可以写出Email用户的正则表达式为^[_a-zA-Z0-9-]+$,这个正则表达式的含义是:以至少一个规范字符(除了.)开头的字符串。
(2)写服务器域名部分的正则表达式,这个表达式可以是[0-9a-z][0-9a-z-]+\.)+[a-z]{2,4},注意最后的[a-z]{2,4},它表示域名的最后一部分,通常是.com、.cn、.info,即至少2个字符,至多4个字符,所以使用[a-z]{2,4}。
(3)使用@将以上两个正则表达式连起来即可,如以下代码第16行所示。代码21-16是检查Email格式是否合法的完整PHP程序。
代码21-16 使用正则表达式验证Email格式是否合法21-16.php
01 <?php
02 $str_arr = array(
03 "mymail@somesite.com",
04 "my_mail@somesite.com",
05 "my-mail@somesite.com",
06 "my.mail@site.com.cn",
07 "mymail@site.com.ccoomm",
08 "mymail@site.cn",
09 "mymail@@@lsite.com",
10 "mymail@site",
11 "MyMail@somesite.com",
12 "My2007@somesite.com",
13 "163mail_for-me777@somesite.com",
14 ); //
定义邮箱数组
15
16 $patt_email = "/^[_a-zA-Z0-9-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,4}$/"; //
验证邮箱
17
18 foreach ($str_arr as $str)
19 {
20 echo "
字符串"$str"
:是";
21 if (preg_match($patt_email, $str)) //
匹配邮箱
22 {
23 echo "<b>
合法的Email
格式</b>";
24 echo "<br>";
25 echo "<br>";
26 }
27 else
28 {
29 echo "
不合法的Email
格式";
30 echo "<br>";
31 echo "<br>";
32 }
33 }
34 ?>
【代码解析】代码第02~14行首先创建了一个字符串数组$str_arr,第16行设计好验证的正则表达式,然后通过第18~33行的foreach循环来逐个检查Email。这段代码的执行结果如图21-18所示。

图21-18 使用正则表达式验证Email地址的合法性
21.5.4 检查URL地址的正则表达式
本小节将讲述如何创建匹配URL地址的正则表达式。一般URL地址由以下几个部分构成。
·协议名,通常是http:。
·//。
·域名部分。
·路径文件部分,如/abc/123.html。
在21.4.3小节已经使用过域名匹配的正则表达式,这里只需完成其他部分的正则表达式即可。对于://在正则表达式中需要对字符/转义,即\/\/。另外对于整个http://部分,如果URL中不含这部分而URL的其他部分是正确的,那么这样格式的URL也应该算是合法的URL,即http://www.php.net和www.php.net都算是合法的URL。因此,该正则表达式的开头部分是^(http:\/\/)?。
最后加上21.5.3节对域名匹配的正则表达式,即完整的正则表达式是:/^((http:)\/\/)?[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*.+$/。代码21-17是验证URL地址的一个完整PHP程序。
代码21-17 使用正则表达式验证URL地址的合法性21-17.php
01 <?php
02 $str_arr = array(
03 "http://www.myoosite.com",
04 "www.myoosite.com",
05 "http://www.myoosite.com/abc/123.html",
06 "//myoosite.com",
07 ":www.myoosite.com"
08 );
//
定义URL
地址数组
09
10 $patt_url = "/^(http:\/\/)?[a-zA-Z0-9]+(\.[a-zA-Z0-9]+)*.+$/";//
验证URL
的正则表达式
11
12 foreach ($str_arr as $str)
//
遍历数组
13 {
14 echo "
字符串"$str"
:是";
15 if (preg_match($patt_url, $str))
//
匹配URL
16 {
17 echo "<b>
合法的URL
格式</b>";
18 echo "<br>";
19 echo "<br>";
20 }
21 else
22 {
23 echo "
不合法的URL
格式";
24 echo "<br>";
25 echo "<br>";
26 }
27 }
28 ?>
【代码解析】上述代码与代码21-16的结构完全一致,都是先创建一个字符串数组,然后创建正则表达式,最后通过一个循环逐个检查URL地址的正确性。这段代码的执行结果如图21-19所示。

图21-19 使用正则表达式验证URL地址的合法性
下一篇:21.6小结
