资源描述
都说正则体现式极难,那是因为他们没有看这个帖
在某个Linux网站上面有这么的话:"假如你问一下Linux兴趣者最喜欢什么,他也许会回答正则体现式;假如你问他最胆怯什么,除了繁琐的安装配备外他肯定会说正则体现式。"
一、为何PHP程序员要学习正则体现式?
PHP被大量的应用于Web的后台CGI开发,一般是在用户数据数据之后得出某种成果,不过假如用户输入的数据不正确,就会出现问题,例如说某人的生日是"2月30日"!那应当怎么样来检查暑假是否正确呢? 在PHP中加入了正则体现式的支持,让我们能够十分以便的进行数据匹配。PHP中的正则体现式有着能够利用模式匹配找到符合条件的字符串、判断字符串是否合乎条件或者用指定的字符串来替代符合条件的字符串等强大的功效,不学实在太可惜了……
二、什么是正则体现式?
简单的说,正则体现式是一个能够用于模式匹配和替代的强大工具。在几乎所有的基于UNIX/LINUX系统的软件工具中找到正则体现式的痕迹,例如:Perl或PHP脚本语言。另外,JavaScript这种客户端的脚本语言也提供了对正则体现式的支持,目前正则体现式已经成为了一个通用的概念和工具,被各类技术人员所广泛使用。
三、PHP正则体现式的语法汇总和详细简介
"^The": 匹配以 "The"开头的字符串;
"of despair$": 匹配以 "of despair" 结尾的字符串;
"^abc$": 匹配以abc开头和以abc结尾的字符串,实际上是只有abc与之匹配
"notice": 匹配包括notice的字符串
你能够看见假如你没有用我们提到的两个字符(最后一个例子),就是说 模式(正则体现式) 能够出目前被检查字符串的任何地方,你没有把他锁定到两边
这里尚有几个字符 '*', '+',和 '?', 他们用来表示一个字符能够出现的次数或者次序. 他们分别表示:"zero or more", "one or more", and "zero or one." 这里是某些例子:
"ab*": 匹配字符串a和0个或者更多b组成的字符串("a", "ab", "abbb", etc.);
"ab+": 和上面同样,但最少有一个b ("ab", "abbb", etc.);
"ab?":匹配0个或者一个b;
"a?b+$": 匹配以一个或者0个a再加上一个以上的b结尾的字符串.
你也能够在大括号里面限制字符出现的个数,例如
"ab{2}": 匹配一个a背面跟两个b(一个也不能少)("abb";
"ab{2,}": 最少更两个b("abb", "abbbb", etc.);
"ab{3,5}": 2-5个b("abbb", "abbbb", or "abbbbb".
你还要注意到你必须总是指定 (i.e, "{0,2}", not "{,2}".同样,你必须注意到, '*', '+', 和'?' 分别和一下三个范围标注是同样的,"{0,}", "{1,}", 和 "{0,1}"。
目前把一定数量的字符放到小括号里,例如:
"a(bc)*": 匹配 a 背面跟0个或者一个"bc";
"a(bc){1,5}": 一个到5个 "bc."
尚有一个字符 '│', 相称于OR 操作:
"hi│hello": 匹配含有"hi" 或者 "hello" 的 字符串;
"(b│cd)ef": 匹配含有 "bef" 或者 "cdef"的字符串;
"(a│b)*c": 匹配含有这么 - 多个(包括0个)a或b,背面跟一个c
的字符串 的字符串;
一个点('.')能够代表所有的 单一字符:
"a.[0-9]": 一个a跟一个字符再跟一个数字的 (含有这么一个字符串的字符串将被匹配,以后省略此括号)
"^.{3}$": 以三个字符结尾 .
中括号括住的内容只匹配一个 单一的字符
"[ab]": 匹配单个的 a 或者 b ( 和 "a│b" 同样);
"[a-d]": 匹配'a' 到'd'的单个字符 (和"a│b│c│d" 尚有 "[abcd]"效果同样);
"^[a-zA-Z]": 匹配以字母开头的字符串
"[0-9]%": 匹配含有 形如 x% 的字符串
",[a-zA-Z0-9]$": 匹配以逗号在加一个数字或字母结尾的字符串
你也能够把你不想要得字符列在中括号里,你只需要在总括号里面使用'^' 作为开头 (i.e., "%[^a-zA-Z]%" 匹配含有 两个百分号里面有一个非字母 的字符串).
好了,目前我们要用我们所学的来干某些有用的事:构建一个匹配模式去检查输入的信息是否为一个表示money的数字。我们以为一个表示money的数量有四种方式: "10000.00" 和 "10,000.00",或者没有小数部分, "10000" and "10,000". 目前让我们开始构建这个匹配模式:
^[1-9][0-9]*$
这是所变量必须以非0的数字开头.但这也意味着 单一的 "0" 也不能通过测试. 如下是处理的措施:
^(0│[1-9][0-9]*)$
"只有0和不以0开头的数字与之匹配",我们也能够允许一个负号再数字之前:
^(0│-?[1-9][0-9]*)$
这就是: "0 或者 一个以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})?$
不要忘掉加号 '+' 能够被乘号 '*' 替代假如你想允许空白字符串被输入话 (为何?). 也不要忘掉反斜杆 '/' 在php字符串中也许会出现错误 (很普遍的错误). 目前,我们已经能够确认字符串了, 我们目前把所有逗号都去掉 str_replace(",", "", $money) 然后在把类型当作 double然后我们就能够通过他做数学计算了.
结构检查email的正则体现式
好,让我们继续讨论怎么验证一个email地址. 在一个完整的email地址中有三个部分: POP3 用户名 (在 '@' 左边的一切), '@', 服务器名(就是剩余那部分). 用户名能够含有大小写字母阿拉伯数字,句号 ('.'), 减号('-'), and 下划线 ('_'). 服务器名字也是符合这个规则,当然下划线除外.
目前, 用户名的开始和结束都不能是句点. 服务器也是这么. 尚有你不能有两个连续的句点他们之间最少存在一个字符,好目前我们来看一下怎么为用户名写一个匹配模式:
^[_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-]+)*$
Done. 目前只需要用”@”把两部分连接:
^[_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-]+)*$ ',$eamil)
就能够得到是否为email了
正则体现式的其他使用方法
1、提取字符串
ereg() and eregi() 有一个特性是允许用户通过正则体现式去提取字符串的一部分(详细使用方法你能够阅读手册). 例如说,我们想从 path/URL 提取文献名 – 下面的代码就是你需要:
ereg("([^///]*)$", $pathOrUrl, $regs);
echo $regs[1];
2、高级的代换
ereg_replace() 和 eregi_replace()也是非常有用的: 假如我们想把所有的间隔负号都替代成逗号:
ereg_replace("[ /n/r/t]+", ",", trim($str));
3 正则体现式的基本语法:
一个正则体现式,分为三个部分:分隔符,体现式和修饰符。
分隔符能够是除了特殊字符以外的任何字符(例如"/ !"等等),常用的分隔符是"/"。体现式由某些特殊字符(特殊字符详见下面)和非特殊的字符串组成,例如"[a-z0-9_-]+@[a-z0-9_-.]+"能够匹配一个简单的电子邮件字符串。修饰符是用来开启或者关闭某种功效/模式。下面就是一个完整的正则体现式的例子:
/hello.+?hello/is
上面的正则体现式"/"就是分隔符,两个"/"之间的就是体现式,第二个"/"背面的字符串"is"就是修饰符。
在体现式中假如含有分隔符,那么就需要使用转义符号"/",例如"/hello.+?//hello/is"。转义符号除了用于分隔符外还能够执行特殊字符,所有由字母组成的特殊字符都需要"/"来转义,例如"/d"代表全体数字。
4 正则体现式的特殊字符:
正则体现式中的特殊字符分为元字符、定位字符等等。
元字符是正则体现式中一类有特殊意义的字符,用来描述其前导字符(即元字符前面的字符)在被匹配的对象中出现的方式。元字符自身是一个个单一的字符,不过不一样或者相同的元字符组合起来能够组成大的元字符。
元字符:
大括号:大括号用来精准指定匹配元字符出现的次数,例如"/pre{1,5}/"表示匹配的对象能够是"pre"、"pree"、"preeeee"这么在"pr"背面出现1个到5个"e"的字符串。或者"/pre{,5}/"代表pre出现0此到5次之间。
加号:"+"字符用来匹配元字符前的字符出现一次或者数次。例如"/ac+/"表示被匹配的对象能够是"act"、"account"、"acccc"等在"a"背面出现一个或者多个"c"的字符串。"+"相称于"{1,}"。
星号:"*"字符用来匹配元字符前的字符出现零次或者数次。例如"/ac*/"表示被匹配的对象能够是"app"、"acp"、"accp"等在"a"背面出现零个或者多个"c"的字符串。"*"相称于"{0,}"。
问号:"?"字符用来匹配元字符前的字符出现零次或者1次。例如"/ac?/"表示匹配的对象能够是"a"、"acp"、"acwp"这么在"a"背面出现零个或者1个"c"的字符串。"?"在正则体现式中尚有一个非常重要的作用,即"贪婪模式"。
尚有两个很重要的特殊字符就是"[ ]"。他们能够匹配"[]"之中出现过的字符,例如"/[az]/"能够匹配单个字符"a"或者"z";假如把上面的体现式改成这么"/[a-z]/",就能够匹配任何单个小写字母,例如"a"、"b"等等。
假如在"[]"中出现了"^",代表本体现式不匹配"[]"内出现的字符,例如"/[^a-z]/"不匹配任何小写字母!并且正则体现式给出了几个"[]"的默认值:
[:alpha:]:匹配任何字母
[:alnum:]:匹配任何字母和数字
[:digit:]:匹配任何数字
[:space:]:匹配空格符
[:upper:]:匹配任何大写字母
[:lower:]:匹配任何小写字母
[:punct:]:匹配任何标点符号
[digit:]:匹配任何16进制数字
另外下面这些特殊字符在转义符号"/"转义后裔表的含义如下:
s:匹配单个的空格符
S:用于匹配除单个空格符之外的所有字符。
d:用于匹配从0到9的数字,相称于"/[0-9]/"。
w:用于匹配字母,数字或下划线字符,相称于"/[a-zA-Z0-9_]/"。
W:用于匹配所有与w不匹配的字符,相称于"/[^a-zA-Z0-9_]/"。
D:用于匹配任何非10进制的数字字符。
.:用于匹配除换行符之外的所有字符,假如通过修饰符"s"的修饰,"."能够代表任意字符。
利用上面的特殊字符能够很以便的体现某些比较繁琐的模式匹配。例如"//d0000/"利用上面的正则体现式能够匹配万以上,十万一下的整数字符串。
定位字符:
定位字符是正则体现式中又一类非常重要的字符,它的重要作用是用于对字符在匹配对象中的位置进行描述。
^:表示匹配的模式出目前匹配对象的开头(和在"[]"里面不一样)
$:表示匹配的模式出目前匹配对象的末尾
空格:表示匹配的模式出目前开始和结尾的两个边界之一
"/^he/":能够匹配以"he"字符开头的字符串,例如hello、height等等;
"/he$/":能够匹配以"he"字符结尾的字符串即she等;
"/ he/":空格开头,和^的作用同样,匹配以he开头的字符串;
"/he /":空格结束,和$的作用同样,匹配以he结尾的字符串;
"/^he$/":表示只和字符串"he"匹配。
括号:
正则体现式除了能够用户匹配,还能够用括号"()"来统计需要的信息,储存起来,给背面的体现式读取。例如:
/^([a-zA-Z0-9_-]+)@([a-zA-Z0-9_-]+)(.[a-zA-Z0-9_-])$/
就是统计邮件地址的用户名,和邮件地址的服务器地址(形式为之类的),在背面假如想要读取统计下来的字符串,只是需要用"转义符+统计的次序"来读取。例如"/1"就相称于第一个"[a-zA-Z0-9_-]+","/2"相称于第二个([a-zA-Z0-9_-]+),"/3"就是第三个(.[a-zA-Z0-9_-])。不过在PHP中,"/"是一个特殊的字符,需要转义,因此""到了PHP的体现式中就应当写成"//1"。
其他特殊符号:
"|":或符号"|"和PHP里面的或同样,不过是一个"|",而不是PHP的两个"||"!意思就是能够是某个字符或者另一个字符串,例如"/abcd|dcba/"也许匹配"abcd"或者"dcba"。
5 贪婪模式:
前面在元字符中提到过"?"尚有一个重要的作用,即"贪婪模式",什么是"贪婪模式"呢?
例如我们要匹配以字母"a"开头字母"b"结尾的字符串,不过需要匹配的字符串在"a"背面含有诸多个"b",例如"a bbbbbbbbbbbbbbbbb",那正则体现式是会匹配第一个"b"还是最后一个"b"呢?假如你使用了贪婪模式,那么会匹配到最后一个"b",反之只是匹配到第一个"b"。
使用贪婪模式的体现式如下:
/a.+?b/
/a.+b/U
不使用贪婪模式的如下:
/a.+b/
上面使用了一个修饰符U,详见下面的部分。
6 修饰符:
在正则体现式里面的修饰符能够变化正则的诸多特性,使得正则体现式愈加适合你的需要(注意:修饰符对于大小写是敏感的,这意味着"e"并不等于"E")。正则体现式里面的修饰符如下:
i :假如在修饰符中加上"i",则正则将会取消大小写敏感性,即"a"和"A" 是同样的。
m:默认的正则开始"^"和结束"$"只是对于正则字符串假如在修饰符中加上"m",那么开始和结束将会指字符串的每一行:每一行的开头就是"^",结尾就是"$"。
s:假如在修饰符中加入"s",那么默认的"."代表除了换行符以外的任何字符将会变成任意字符,也就是包括换行符!
x:假如加上该修饰符,体现式中的空白字符将会被忽视,除非它已经被转义。
e:本修饰符仅仅对于replacement有用,代表在replacement中作为PHP代码。
A:假如使用这个修饰符,那么体现式必须是匹配的字符串中的开头部分。例如说"/a/A"匹配"abcd"。
E:与"m"相反,假如使用这个修饰符,那么"$"将匹配绝对字符串的结尾,而不是换行符前面,默认就打开了这个模式。
U:和问号的作用差不多,用于设置"贪婪模式"。
7 PCRE有关的正则体现式函数:
PHP的Perl兼容正则体现式提供的多个函数,分为模式匹配,替代和匹配数目等等:
1)、preg_match :
函数格式:int preg_match(string pattern, string subject, array [matches]);
这个函数会在string中使用pattern体现式来匹配,假如给定了[regs],就会将string统计到[regs][0]中,[regs][1]代表使用括号"()"统计下来的第一个字符串,[regs][2]代表统计下来的第二个字符串,以此类推。preg假如在string中找到了匹配的pattern,就会返回"true",否则返回"false"。
2)、preg_replace :
函数格式:mixed preg_replace(mixed pattern, mixed replacement, mixed subject);
这个函数会使用将string中符合体现式pattern的字符串所有替代为体现式replacement。假如replacement中需要包括pattern的部分字符,则能够使用"()"来统计,在replacement中只是需要用"/1"来读取。
3)、preg_split :
函数格式:array preg_split(string pattern, string subject, int [limit]);
这个函数和函数split同样,区分仅在与split能够使用简单正则体现式来分割匹配的字符串,而preg_split使用完全的Perl兼容正则体现式。第三个参数limit代表允许返回多少个符合条件的值。
4)、preg_grep :
函数格式:array preg_grep(string patern , array input);
这个函数和preg_match功效基本上,不过preg_grep能够将给定的数组input中的所有元素匹配,返回一个新的数组。
下面举一个例子,例如我们要检查Email地址的格式是否正确:
复制代码 代码如下:
<?php
function emailIsRight($email) {
if (preg_match("^[_/.0-9a-z-]+@([0-9a-z][0-9a-z-]+/.)+[a-z]{2,3}$",$email)) {
return 1;
}
return 0;
}
if(emailIsRight('')) echo '正确<br>';
if(!emailIsRight('y10k@fffff')) echo '不正确<br>';
?>
上面的程序会输出"正确<br>不正确"。
8.PHP中的Perl兼容正则体现式和Perl/Ereg正则体现式的区分:
虽然叫做“Perl兼容正则体现式”,不过和Perl的正则体现式相比,PHP的还是由某些不一样,例如修饰符“G”在Perl里面代表所有匹配,不过在PHP中没有加入对这个修饰符的支持。
尚有就是和ereg系列函数的区分,ereg也是PHP中提供的正则体现式函数,不过和preg相比,要弱上诸多。
1)、ereg里面是不需要也不能使用分隔符和修饰符的,因此ereg的功效比preg要弱上不少。
2)、有关".":点在正则里面一般是除了换行符以外的所有字符,不过在ereg里面的"."是任意字符,即包括换行符!假如在preg里面希望"."能够包括换行符,能够在修饰符中加上"s"。
3)、ereg默认使用贪婪模式,并且不能修改,这个给诸多替代和匹配带来麻烦。
4、速度:这个或许是诸多人关心的问题,会不会preg功效强大是以速度来换取的?不用担心,preg的速度要远远比ereg快,笔者做了一个程序测试:
time test:
PHP代码:
复制代码 代码如下:
<?php
echo "reg_replace used time:";
$start = time();
for($i=1;$i<=100000;$i++) {
$str = "ssssssssssssssssssssssssssss";
preg_replace("/s/","",$str);
}
$ended = time()-$start;
echo $ended;
echo "
ereg_replace used time:";
$start = time();
for($i=1;$i<=100000;$i++) {
$str = "ssssssssssssssssssssssssssss";
ereg_replace("s","",$str);
}
$ended = time()-$start;
echo $ended;
echo "
str_replace used time:";
$start = time();
for($i=1;$i<=100000;$i++) {
$str = "sssssssssssssssssssssssssssss";
str_replace("s","",$str);
}
$ended = time()-$start;
echo $ended;
?>
成果:
Preg_replace used time:5
ereg_replace used time:15
str_replace used time:2
str_replace因为不需要匹配因此速度非常快,而preg_replace的速度比ereg_replace要快上不少。
展开阅读全文