******** 4.6 正则表达式的介绍 (from book 《 PHP & MySQL Web Development》)
PHP 支持两种格式的正则表达式语法:POSIX 和 Perl。
用途:完成复杂的模式匹配。
难度:难
******** 4.6.1 基础知识 ******
定义:正则表达式是一种描述一段文本模式的方法。
类比:strstr()函数,是在一个字符串的某个位置(如果不指明则可能在字符串中的任何位置)匹配另一个字符串。
例子:字符处"shop"匹配正则表达式"shop",也可以匹配正则表达式"h","ho"等。
其他:除了精确匹配字符串外,还可以用特殊字符来指定表达式的元意(meta-meaning)。
例如:使用特殊字符,可以指定一个在字符串开始或末尾肯定存在的模式,该模式的某部分可能被重复,或
模式中的字符属于特定的某一类型。此外,还可以按特殊字符的出现来匹配。
******* 4.6.2 字符集和类 ******
字符集可以用来匹配属于特定类型的任何字符,是一种通配符。
例如:可以用字符作为一个通配符来代替除了换行符(\n)之外的任意字符。
==>正则表达式 .at 可以与"cat","sat" ,"mat"等进行匹配。(这种通配符用于OS中的文件名匹配)
此外,使用正则表达式可以更具体地指明希望匹配的字符类型,而且可以指明字符所属的一个集合。
例如:.at可以匹配"cat","sat","mat",也可以匹配"#at";如果要限定它是a到z之间的字符,可以这
样声明==>[a-z]at
任何包含在[ ]中的内容都是一个字符类 -- 一个被匹配字符所属的字符集合,
(方括号内的表达式只匹配一个字符)
==>[aeiou]集合可以表示元音字母;[a-zA-Z]集合表示任何的大小写字母;
[^a-z]集合指明字符不属于某个集(即匹配任何不在a到z之间的字符)
表4-3 用于POSIX风格的正则表达式的字符类
————————————————————————————
类 匹 配
[[:alnum:]] 文字数字字符 '[:alpha:]' and '[:digit:]’
[[:alpha:]] 字母字符 '[:lower:]' and '[:upper:]'
[[:lower:]] 小写字符
[[:upper:]] 大写字符
[[:digit:]] 小数 0 1 2 3 4 5 6 7 8 9
[[:xdigit:]] 十六进制数 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f
[[:punct:]] 标点符号 ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ' { | } ~
[[:blank:]] 制表符和空格 space and tab
[[:space:]] 空白字符
[[:cntrl:]] 控制符
[[:print:]] 所有可打印的字符 '[:alnum:]', '[:punct:]', and space
[[:graph:]] 除空格外所有可打印的字符 '[:alnum:]' and '[:punct:]'
———————————————————————————————————————
******** 4.6.3 重复 **************
" * "符号表示这个模式可以被重复0次或多次;
" + "符号表示这个模式可以被重复1次或多次。
(这两个符号要放在要作用的表达式的后面)
例子:[[:alnum:]]+ == "至少有一个字母字符"
******** 4.6.4 子表达式 *************
将一个表达式分割成几个子表达式,例如,可以表示“至少这些字符串中的一个需要精确匹配”。
用()符号来实现:(very) * large 可以匹配“large”,“very large”,“very very large”等。
******** 4.6.5 子表达式计数 ************
用在 { } 中的数字表达式来指定内容允许重复的次数。
例子:{3}表示重复3次;{2,4}表示重复2-4次;{2,}表示至少重复2次
==> (very){1,3} 表示匹配“very”、“very very”和“very very very”。
******** 4.6.6 定位到字符串的开始或末尾 ***********
[a-z]模式将匹配任何包含了小写字母字符的字符串。无论该字符串只有一个字符,或者在整个更长的字符串中只包含
一个匹配的字符。
也可以确定一个特定的子表达式是否出现在开始、末尾或者两个位置都出现。
脱字符号(^)用于正则表达式的开始,表示子字符串必须出现在被搜索字符串的开始处。
“$”用于正则表达式的末尾,表示子字符串必须出现在被搜索字符串的末尾。
例子:^bob 在字符串开始处匹配Bob;
com$ 匹配com出现在字符串末尾处的字符串;
^[a-z]$ 匹配只包含a到z之间一个字符的字符串。
******** 4.6.7 分支 ******************
使用正则表达式中的一条竖线表示一个选择。
例子:com|edu|net 匹配com,edu或net
******** 4.6.8 匹配特殊字符 **********
如果要匹配特殊字符,例如:.,{或者$,就必须在前面加上反斜杠(\)
在PHP中,必须将正则表达式模式包含在一个单引号字符串中。
******** 4.6.9 特殊字符一览 ***********
表4-4 在POSIX正则表达式中,用于方括号外面特殊字符的摘要
————————————————————————————————————
字 符 意 义
\ 转义字符
^ 在字符串开始处匹配
$ 在字符串末尾处匹配
. 匹配除换行符\n之外的字符
| 选择分支的开始(或)
( 子模式的开始
) 子模式的结束
* 重复0次或多次
+ 重复1次或多次
{ 最小/最大量记号的开始
} 最小/最大量记号的结束
? 标记一个子模式为可选的
——————————————————————————————————————
表4-5 POSIX正则表达式中,用于方括号里面特殊字符的摘要
————————————————————————————————————
字 符 意 义
\ 转义字符
^ 非,仅用在开始
- 用于指明字符范围
————————————————————————————————————
*********** 4.6.10 在智能表单中应用 ************
在只能表单应用程序中,正则表达式有两种用途:
1.在顾客的反馈信息中查找特定的名词。
以往做法:使用字符串函数strstr(),如果想匹配"shop","customer service","retail"则需要做3次不同的搜索
==> strstr($string,'shop'); strstr($string,'customer service'); strstr($string,'retail');
用正则:可以同时匹配"shop","customer service","retail"
==> shop|customer service|retail
2.验证程序中用户的电子邮件地址。
以往做法:使用字符串函数。
用正则:对电子邮件地址的标准格式进行编码。
(数字/标点符号 + @ +文字/数字/字符组成的字符串 + . +文字/数字以连字符组成的字符串)
==> ^[a-zA-Z0-9_\-.]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-.]+$
其中^[a-zA-Z0-9_\-.]+表示“至少由一个字母(任意大小写)、数字、下划线、连字符、点号(.)或者
这些字符组合为开始的字符串”
(start the string with at least one letter,number,underscore,hyphen,or dot,or some combination
of those);
tip:当在一个字符类的开始或末尾处使用点号时,点号将失去其特殊通配符的意义,只能成为一个点号符号。
@ 匹配字符 @;
[a-zA-Z0-9\-]+与包含文字数字字符和连字符的主机名匹配;
字符组合 \. 匹配 “.”字符;(我们在字符类外部使用点号,必须对其进行转义,让它能够匹配一个点号符号)
[a-zA-Z0-9\-.]+$匹配域名的剩下部分(com、net等),它包含字母、数字、连字符,如果需要还可以包含更多的点号直到字符串的末尾。
************* 4.7 用正则表达式查找子字符串
在PHP中,可以使用的并且用于匹配POSIX风格的正则表达式的两个函数是ereg()和eregi()
ereg(): int ereg(string $pattern, string $string [, array &$regs]);
以区分大小写的方式在 string 中寻找与给定的正则表达式 pattern 所匹配的子串。
如果找到与 pattern 中圆括号内的子模式相匹配的子串并且使用了第三个参数regs,则
匹配项将被存入regs数组中。
$regs[1]包含第一个左圆括号开始的子串,以此类推。
$regs[0]包含整个匹配的字符串。
如果string中找到pattern模式的匹配则返回所匹配字符串的长度,如果没有找到匹配或者出错则返回FALSE,
如果没有使用第三个参数或者所匹配的字符串长度为0,则函数返回1.
eregi():不区分大小写,其余与ereg()一样。
下面是改进的智能表单(Smart Form):
if(!mb_eregi('^[a-zA-Z0-9_\-\.]+@[a-zA-Z0-9\-]+\.[a-zA-Z0-9\-\.]+$',$email)){
echo "<p>That is not a valid email address.</p>"."<p>Please return to the previous page and try again.</p>";
exit;
}
$toaddress = "feedback@example.com"; //the default value
if(mb_eregi("shop|customer service|retail",$feedback)){
$toaddress = "retail@example.com";
}else if(mb_eregi("deliver|fulfill",$feedback)){
$toaddress = "fulfillment@example.com";
}else if(mb_eregi("bill|account",$feedback)){
$toaddress = "account@example.com";
}else{
$toaddress = "feedback@example.com";
}
if(mb_eregi("bigcustomer\.com",$email)){
$toaddress = "bob@example.com";
}
********************** 4.8 用正则表达式替换子字符串
函数:ereg_replace() / eregi_replace()
原型:string ereg_replace(string pattern, string replacement, string search);
意义:该函数在字符串search中查找正则表达式pattern的字符串,并且用字符串replacement替换。
********************** 4.9 使用正则表达式分割字符串
函数:split()
原型:array split(string pattern, string search[, int max]);
意义:将字符串search分割成符合正则表达式模式的子字符串,然后把子字符串返回到一个数组中,max指定进入数组中的元素个数。
例子:分割电子邮件地址
#split()
$address = "username@example.com";
$arr = mb_split("\.|@",$address);
while(list($key, $value) = each($arr)){
echo "<br />".$value;
}
输出结果与书上不同,书上是把分隔符也输出一行,实际是去掉了分隔符
结果:
username
example
com