简介:PHP支持两套正则表达式处理函数库。
一套是由PCRE(Perl Compatible Regular Expression)库提供的,与perl语言兼容的正则表达式函数。使用preg_为前缀命名的函数,而且表达式都包含在定界符中如斜线(/)。
另一套是有POSIX(portable Operation Ststem interface)扩展语法的正则表达式函数,以ereg_为前缀命名的。两套功能相似,效率稍有不同。
一般实现相同功能使用第一种PCRE库提供的正则效率略占优势。所以一下主要介绍使用preg_为前缀敏敏的正则表达式函数。
preg_match() | 进行正则表达式匹配 | preg_replace() | 执行正则表达式的搜索和替换 |
preg_match_all() | 进行全局正则表达式匹配 | preg_replace_callback() | 用回调函数执行正则表达式的搜索和替换 |
preg_split() | 用正则表达式分割字符串 | preg_grep() | 返回模式匹配的数组单元 |
正则表达式语法规则
正则表达式描述可一种字符串匹配模式,通过这个模式在特定函数中队字符串进行匹配查找替换以及分割等操作。
正则表达式作为一个匹配模板,是由:
- 原子(普通字符,如字符a到Z)
- 有特定特殊功能的字符(称为元字符,例如*、+、?等)
- 以及模式修正符
三部分组成的文字模式。一个最简单的正则表达式模式中至少要包含一个原子,如“/a/”。而且在与Perl兼容的正则函数中使用模时,一定要给模式加定界符即包含在两个反斜线“/”之间。
1、定界符
使用与Perl兼容的正则表达式,通常需要将表达式放进定界符之间,定界符也不仅仅局限于视同反斜线"/",除了字母数字和正斜线“\”以外的任何字符都可以作定界符,例如#、!、{}、和|等都可以的。通常习惯都将模式表达式包含在两个反斜线之间。
例如:/<\/\w+>/ //使用反斜线合法
!^(?i)php[34]!//使用感叹号作为定界符合法
/href='(.*)'//非法定界符号,缺少结束定界符
1-\d3-\d3-\d4|//非法定界符号,缺少开始定界符
2、原子
原子是正则的最基本组成单位,而且每个模式至少包含一个原子。原子是由哪些未显示指定为元字符的打印和非打印字符组成,包括所有大小写字母字符、所有数字、所有标点符号以及一些其他符号例如:a~z、A~Z、0~9、双引号、单引号等。还包括一些非打印字符
\f | 匹配一个换页符。等价于\x0c和\cL | \s | 匹配任何空白字符,包括空格、制表符、换页符等等价于[\f\r\n\t\v] |
\n | 匹配一个换行符。等价于\x0a和\cJ | \S | 匹配任何非空白字符等价于[^\f\n\r\t\v] |
\r | 匹配一个回车符。等价于\x0d和\cM | \t | 匹配一个制表符等价于\x09和\cI |
\v | 匹配一个垂直制表符等价于\x0b和\cK |
\cx 匹配一个由x指明的控制字符,例如\cM匹配一个Control-M或回车符。x值必须为A~Z或者a~z之一,否则,将c视为一个原义的“c”字符
3、元字符
元字符就是用于构建正则表达式的具有特殊含义的字符例如:* + ?等。如果正则表达式包含元字符本身,使其失去特殊含义则必须加上\进行转义。
利用Perl正则表达式还可以做另一件有用的事情,使用各种元字符来搜索匹配。
正则表达式有以下特殊字符:
\d | 匹配任意一个十进制数字等价于[0-9] | {n} | 表示其前面的原子恰好出现n次 |
\D | 匹配任意一个除了十进制数以外的字符,等价于[^0-9] | {n,} | 表示其前面的原子出现不少于n次 |
\s | 匹配任意一个空白字符,等价于[\f\n\r\t\v] | {n,m} | 表示其前面的原子出现n次,最多出现m次 |
\S | 匹配除了空白字符以外的任何一个字符等价于[^\f\n\r\t\n] | ^或\A | 匹配输入字符串的开始位置(或在多行模式下行的开头,即紧随一换行符之后) |
\w | 匹配任意一个数字、字母、或下划线,等价于[0-9a-zA-Z_] | $或\Z | 匹配输入字符串的结束位置(或在多行模式下行结尾,即紧随一换行符之前) |
\W | 匹配除了数字、字母、下划线以外的任意一个字符、等价于[^0-9a-zA-Z_] | \b | 匹配单词边界 |
* | 匹配0次、1次、或多次其前的原子 | \B | 匹配除了单词边界以外的部分 |
+ | 匹配1次或多次其前的原子 | [] | 匹配方括号中指定的任意一个原子 |
? | 匹配0次或者1次其前的原子 | [^] | 匹配除方括号中原子以外的任意一个字符 |
. | 匹配出科换行符外的任意一个字符 | () | 匹配其整体为一个原子,即模式单元,可以理解为由多个单原子组成的大原子 |
| | 匹配两个或多个分支选择 |
元字符是构建正则表达式的最重要部分,下面分为几类分别讲解:
一、通用字符类型
通用字符类型可以匹配相应类型的一个字符,如\d可以匹配数字类型中的任意一个十进制数。共有6中通用字符类型,包括"\d"和"\D"、"\s"和"\S","\w"和“\W"。
当然也可以使用原子表制定出这种通用字符类型,如[0-9]和"\d"功能是一样的,都可以匹配一个十进制数。
/^[0-9a-zA-Z_]+@[0-9a-zA-Z_]+(\.[0-9a-zA-Z_]+){0,3}$/ //匹配E-mail的正则表达式模式
/^\w+@\w+(\.\w+){0,3}$/ //也是匹配邮箱的
--------------------------------
-细说PHP的正则讲的太复杂,以下是另一篇讲解正则的笔记。-----------------------
基础介绍:
正则表达式可以让用户通过一系列的特殊字符构建匹配模式,然后把匹配模式与数据文件、程序输入以及web页面的表单输入等目标对象进行比较,根据比较对象中是否包含匹配模式执行相应程序。
(一)、^和$他们分别是用来匹配字符串的开始和结构,例如:"^The":开头一定要有The字符串; "of despair$":结尾一定要有"of despair"的字符串;那么"^abc$":就是要求以abc开头和以abc结尾的字符串,实际上是只有abc匹配。"notice":匹配包含notice的字符串;(如果没有用提到的两个字符^和$就是说正则表达式可以出现在被校验的字符串的任何地方,你没有把他锁定在两边)
(二)接着*+和?:他们用来表示一个字符可以出现的次数或者顺序,他们分别表示零或多次相当于{0,};一或多次{1,};零或一次{0,1}例如:
"ab*":和ab{0,}同义,匹配以a开头,后面可以接0个或者N个b组成的字符串("a","ab",”abbb“,等);
”ab+“:和ab{1,}同义,同上条一样,但最少要有一个b存在("ab","abbb",等);
"ab?":和ab{0,1}同义,可以没有或者只有一个b("a","ab");
"a?b+$":匹配一个或者0个a再加上一个以上的b结尾的字符串。
要点,*+和?只管它前面的那个字符。你也可以再大括号里面限制字符出现的个数,如:
"ab{2}":要求a后面一定要跟两个b(一个也不能少)("abb");
"ab{2,}":要求a后面一定要有两个或者两个以上的b("abb","abbb",等);
"ab{3,5}":要求a后面可以有2-5个b("abbb","abbbb"or"abbbbb");
现在我们把一定几个字符放在小括号里,比如:
"a(bc)*" :匹配a后面跟着0个或者一个"bc";
"a(bc){1,5}”:匹配a 后面跟着1个到5个"bc"
(三)还有一个字符“|”,相当于OR操作:
"hi | hello":匹配有hi或者hello的字符串;
"(b | cd)ef":匹配含有bef或者cdef的字符串;
“(a|b)*c”:匹配含有这样多个(包括0个)a或b,后面跟一个c的字符串;
一个点(.)可以代表所有的单一字符,不包括"\n";如果要匹配包括"\n"在内的所有单个字符,怎么办?用"[\n.]"这个模式。
"a.[0-9]" :一个a 加上一个字符再加上一个0-9的数字;
"^.{3}$" :三个任意字符结尾;
中括号住的内容只匹配一个单一字符:
"[ab]":匹配单个a或者b(和"a | b"一样);
"[a-d]":匹配'a'到'd'的单个字符(和"a | b | c | d"还有"[abcd]"效果一样);一般我们都用[a-zA-Z]来指定字符为一个大小写英文;
"^[a-zA-Z]":匹配以大小写字母开头的字符串;
"[0-9]%":匹配含有形如x%的字符串;
",[a-zA-Z0-9]$":匹配以逗号再加一个数字或者字母结尾的字符串;
也可以把不想要的字符列在中括号里面,只需要在中括号里面使用'^'作为开头“%[^a-zA-Z]%”匹配含有两个百分号里面有一个非字母的字符串。
要点:^用在中括号开头时候,表示排斥括号里面的字符。
正则手册里面介绍:如果列表里含有']',最好把它作为列表里的第一个字符(可能跟在^后面)
{n,m}要注意的是n和m都不能为负整数,而且n总是小于m,这样才能最少匹配n次最多匹配m次,如:p{1,5}将匹配'pvpppppp'中的前五个p
(四)以\开头的
\b 书上说是用来匹配一个单词的边界,如:"ve\b",可以匹配love里的ve而不匹配very里有ve。
\B正好相反。
做个应用,如何构建一个模式来匹配货币数量的输入,构建一个匹配模式的信息是否为一个表示money的数字,表示money的数量有四种方式:10000.00、10,000.00、或者没有小数部分10000、10,000。现在开始构建这个模式:^[1-9][0-9]*$这是必须以非0数字开头,但这也意味着单一的0也不能通过测试。解决方法:^(0|[1-9][0-9]*)$只有0和不以0开头的数字与之匹配。
我们也可以允许一个负号在数字之前:^(0|-?[1-9][0-9]*)$ 这就是0或者一个以0开头且有可能有一个负号在前面的数字。现在放弃负号,因为我们在表示钱币的时候并不需要用到。
我们现在指定模式用来匹配小数部分:^[0-9]+(\.[0-9]+)?$ 这暗示匹配字符串必须最少以一个数字开头。这个模式"10."是不匹配的,只有10和10.2才可以。
^[0-9]+(\.[0-9]{2})?$这个指定小数点后面必须有两位小数,改成不那么苛刻:^[0-9]+(\.[0-9]{1,2})?$这将允许小数点后面有一个到两个字符。
现在加上用来增加可读性的逗号(每个三位):^[0-9]{1,3}(,[0-9]{3})*(\.[0-9]{1,2})?$
不要忘记+可以被*替代。
构建检查email的正则表达式:
在一个完整的email地址中有三个部分:1.用户名(在"@"左边的一切),2.“@” 3.服务器名(就是剩下那部分)。
用户名可以含有大小写字母数字句号减号和下划线 服务器名字也是符合这个规则,当然下划线除外。
现在,用户名的开始和结束都不能是句点.服务器也是这样.还有不能有两个连续的句点他们之间至少存在一个字符,
现在为用户名写一个匹配模式:^[_a-zA-Z0-9-]+$
上面不能允许句号存在,现在加上:^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*$ 这个意思是:以至少一个规范字符(除了.)开头,后面跟着0个或者多个以点开始的字符串
简化点可以用eregi()取代ereg()。eregi()对大小写不敏感,我们就不需要指定两个范围“a-z”和"A-Z" 只需要指定一个就可以了:^[_a-z0-9-]+(\.[_a-z0-9-]+)*$
后面服务器名字也是一样,但要去掉下划线:^[a-z0-9-]+(\.[a-z0-9-]+)*$
现在用@把两部分连接:^[a-z0-9_-]+(\.[a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$ 这就是完整的email认证的匹配模式了,
只需要调用eregi(‘^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*$’,$email) 就可以得到是否为email
正则表达式的其他用法
提取字符串:ereg()和eregi有一个特性是允许用户通过正则表达式提取字符串一部分(具体阅读手册)。
比如,想要从path/URL提取文件名:
ereg("([^\V]*)$",$pathOrUrl,$regs);
echo $regs[1];
高级的代换:ereg_replace()和eregi_replace()假如想把所有间隔符号都替换成逗号:
ereg_replace("[\n\r\t]+",",",trim($str));
基本语法
对正则表达式的功能和作用有初步了解之后,具体看下正则表达式语法格式。
正则表达式的形式一般如:/love/
其中位于"/" 定界符之间的部分就是将要在目标对象中进行匹配的模式。用户把希望匹配的模式内容放进/定界符之间即可。
为了灵活定制模式,正则提供专门的“元字符”。元字符指那些在正则中具有特殊意义的专用字符,可以用来规定其前导字符(即位于元字符前面的字符)在对象中出现的模式
常用的元字符包括:+ * ? 其中,加号元字符规定其签到字符必须在目标对象中连续出现一次或者多次,星号元字符规定出现零次或连续多次,问号元字符规定连续出现零次或者一次。
例如:/fo+/ 因为正则中包含+,表示可以与目标对象中的 fool ,fo 或者football等在字母f 后面连续出现一个或者多个字母o的字符串相匹配
/eg*/ 正则中包含*元字符,表示可以与目标对象中easy ego 或者 egg等在字母e后面连续出现零个或多个字母g的字符串相匹配。
/Wil?/ 包含?元字符 ,可以与目标中的Win 或者Wilson 等在字母i后面连续出现零个或一个字母1的字符串相匹配。
除了元字符外还可以精确指定模式在匹配对象中出现的频率,如:/jim{2,6}/ 表示规定字符m可以再匹配对象中连续出现2-6次同jimmy或jimmmmmy等相匹配
接下来了解其他几个重要的元字符使用方式:右边定位符
\d | 匹配任意一个十进制数字等价于[0-9] | {n} | 表示其前面的原子恰好出现n次 |
\D | 匹配任意一个除了十进制数以外的字符,等价于[^0-9] | {n,} | 表示其前面的原子出现不少于n次 |
\s | 匹配任意单个空白字符,等价于[\f\n\r\t\v] | {n,m} | 表示其前面的原子出现n次,最多出现m次 |
\S | 匹配除了空白字符以外的任何一个字符等价于[^\f\n\r\t\n] | ^或\A | 匹配输入字符串的开始位置(或在多行模式下行的开头,即紧随一换行符之后) |
\w | 匹配任意一个数字、字母、或下划线,等价于[0-9a-zA-Z_] | $或\Z | 匹配输入字符串的结束位置(或在多行模式下行结尾,即紧随一换行符之前) |
\W | 匹配所有与\w不匹配的字符 | \b | 匹配单词边界,规定必须出现在字符串的开头或结尾两个边界之一 |
. | 匹配除换行符之外的所有字符 | \B | 匹配除了单词边界以外的部分 |
+ | 匹配1次或多次其前的原子 | [] | 匹配方括号中指定的任意一个原子 |
? | 匹配0次或者1次其前的原子 | [^] | 匹配除方括号中原子以外的任意一个字符 |
. | 匹配出科换行符外的任意一个字符 | () | 匹配其整体为一个原子,即模式单元,可以理解为由多个单原子组成的大原子 |
| | 匹配两个或多个分支选择 |
例:/^hell/ 可以与目标对象中以hell hello 或hellhound 开头的字符串相匹配
/ar$/ 可以与目标对象中以 car bar 或ar结尾的字符串相匹配。
/\bbom/ 因为以\b开头,所以可以与目标对象中以bomb或者 bom开头的字符串相匹配
/man\b/因为以\b定位符结尾,所以可以与目标对象中 human woman 或man结尾的字符串相匹配。
正则表达式允许使用者在匹配模式中指定某一个范围而不局限于具体字符
如:/[A-Z]/ 将会与A到Z范围内的任和一个大写字母相匹配
/[a-z]/ 上述正则表达式将会与从a到z范围内任何一个小写字母相匹配
/[0-9]/ 将会与0到9范围内任何一个数字匹配
/([a-z][A-Z][0-9])/ 将会与任何由字母和数字组成的字符串,如aB0相匹配。需要注意 的是:可以在正则表达式中使用()把字符串组合在一起,()符号包含的内容必须同时出现在目标对象中,因此这个表达式无法与如abc等字符串匹配,因为abc最后一个字符为字母而非数字。
/to|too|2/ 此表达式将与目标对象中的to too 或2匹配。
/[^A-C]/ [^]否定符,与定位符^不同,否定符规定目标对象中不能存在模式中所规定字符,此字符串将会与除ABC之外的任何字符匹配
一般来说当^出现在[]内就被视作否定符;而当^位于[]之外则应被视作定位符。
正则表达式中的一些特殊字符
\当用户需要在正则表达式模式中加入元字符并查找其匹配对象时,可以使用转义字"\",例如:/Th\*/ 此正则将会与Th*而非The等相匹配
字符^ 意义:表示匹配的字符必须在最前边,如:/^A/不匹配anA中的 A,但匹配"An A"中的最前面A。
字符$ 意义:与^类似,匹配最末字符 ,如:/t$/ 不匹配 eater中的t ,但匹配eat中的t。
字符* 意义:匹配前面的字符0次或者n次,等价于{0,},例如:/bo*/ 匹配"A ghost booooed" 中的boooo或 A bird warbled中的b,但不匹配Agoat grunted中的任何字符。
字符+意义:匹配前面字符1次或者n次,等价于{1,}。例如:/a/匹配candy中的‘a’ 和"caaaaaandy"中的所有a。
字符? 意义:匹配前面字符0次或者1次,等价于{0,1}。例如:/e?le?/匹配angel中的el和angle中的le
字符.意义:小数点匹配除换行符外所有的单个字符。例如:/.n/ 匹配"nay,an apple is on the tree"中的" an" 和" on "但不匹配" nay"。