原文地址:http://blog.csdn.net/mu_rain/article/details/5435745
1 正则是什么.
请先看 http://www.PHPchina.com/html/11/n-34811.html 几k 的解释后.
原地址已被更改,重新找了一个教程,请点击。 http://deerchao.net/tutorials/regex/regex.htm 2 实例剖析. 1. $str = '<FORM&NBSP;NAME="ADFA"&NBSP;ACTION="ASDF.BPHP"&NBSP;TARGET=""><FORM&NBSP;NAME="BBBB"&NBSP;ACTION="HTTP: www.bac.com test.PHP? target="qwerqwerq"><FORM&NBSP;NAME="BBBB"&NBSP;ACTION="HTTP.PHP"&NBSP;TARGET="QWERQWERQ">'; 2. $match = ''; 3. preg_match_all('//s+action=/"(?!http:)(.*?)/"/s/',$str,$match); 4. print_r($match); //s+action=/"(?!http:)(.*?)/"/s/ 此正则是用来匹配 action=”xxx” 里面的xxx的. 可讲的地方有3 1 /”(.*?)/” 会匹配 aa”abb”aaaa” 字符串中的”abb”” 而(.*)/” 则会去匹配aa”abb”aaaa”中的”abb”aaaa”. 此谓之贪婪(greedy) 特别实用。U 修正符可以反转正则式中的贪婪。 2 (?!http:) 代表将要匹配的内容中不含有http: 他本身不匹配内容. 例如 我要匹配一个 长为8-16里面不能有http 的字符串,就写 (?!http)/w{8-16} 即可。 3 就是这哥们匹配时,定死了action=” 后面的这个(“) 如果是 ‘ 号呢怎么办呢? 这里就要用到 反向引用了。 相关正则表达式如下。 (?<=/s*action=('|/"))(?!|http)(.*?)(?=/1) 演化一下 最初的想法 Action=/”(.*)/” => 为能只匹配 action=”dddd” fdsfds” 中的action=”dddd”而不是action=”dddd” fdsfds” 更改为action=/”(.*?)/” =>要支持单引号action=(‘/”)(.*?)/1 => action 后面引号内不允许有http action=(‘/”)(?!http:)(.*?)/1 => 只想提取引号内的内容,不想提取其它的内容. (?<=/s*action=('|/"))(?!http)(.*?)(?=/1) 文中还有两个例子挺实用的。 带断言的正则匹配 1. $match = ''; 2. $str = '<A&NBSP;HREF="">xxxxxx.com.cn <b>ddddbolod</b>paragraph text '; 3. preg_match_all ( '/(?<=<(/w{1})>).*(?=<///1>)/',$match ); 4. echo "<BR&NBSP; />匹配没有属性的标签中的内容:"; 5. print_r ( $match ); 正则式为(?<=<(/w{1})>).*(?=<///1>) (?<=<(/w{1})>) 为逆向预匹配,就是说需要匹配的左边要满足这要求。 上PHP手册查了一下,preg_match_all("/(<([/w]+)[^>]*>)(.*?)(<////2>)/",$html,$matches,PREG_SET_ORDER); 然后表大式可以更改为(?<=<(/w+)>).*(?=<///1>) 替换HTML源码中的地址 1. $form_html = preg_replace ( '/(?<=/saction=/"|/ssrc=/"|/shref=/")(?!http:|javascript)(.*?)(?=/"/s)/e','add_url(/$url,/'//1/')',$form_html ); 这个也是单双引号的问题,需要改改. 2 看完帖http://www.PHPchina.com/html/03/n-34203.html 觉得 function is_good_pw($pw) { if(preg_match('/(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{8,16}/',$pw)) { return true; } return false; } 可以吸收一下。下面我决定啰哩啰嗦的解试一下这个函数。 .{8-16} 代表匹配8-16位非换行字符串。 可是当我们需要这8-16 位的数字中,必须有数字,而且有小写字母,而且有大写字母时,正则表达式如何去写呢? (?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{8,16} 匹配 必须有数字,小写字母,大写之母的 的8-16 位的字符. 1 基础概念讲解. 1 理解缝隙的概念. 例如,"^","$","/b"。它们都有一个共同点,那就是:它们本身不匹配任何字符,只是对 "字符串的两头" 或者 "字符之间的缝隙" 附加了一个条件 2 ?=xxx) 正向预搜索 代表缝隙的右侧,必须能够匹配上 xxxxx 这部分的表达式 那么 (?=.*[/d]).{8-16} 代表匹配含有数字的8-16位的字符串, 如果是(?=/d).{8-16}则匹配的内容为首位为数字的8-16 的字符串. 如果是(?=/d{2}).{8-16}则匹配的内容为前两位为数字的8-16 的字符串. 从这里看来,正向预搜索需要理解的就是(?=xxx) 本身是不匹配字符的,而是给右侧的字符串添加条件,目的就是要右侧的字符串能满足这个预搜索条件。 .{8-16} 代表任意非换行的8 位字符串. (?=.*[/d]).{8-16} 代表任意非换行的8-16 位字符串,而且这8-16位字符串中有数字。 (?=.*[/d]) (?=.*[a-z]).{8-16}代表任意非换行的8-16 位字符串,而且这8-16位字符串中有数字,而且这8-16位字符串中有a-z 之间的字母. 这样看来(?=.*[/d]).{8-16}的(?=.*[/d])就是用来向.{8-16}来叠加规则的.*[/d] 的 (?=.*[a-z]) (?=.*[/d]).{8-16} 中的(?=.*[a-z])就是用来向(?=.*[/d]).{8-16}叠加(?=.*[a-z])规则。 这样下来,当我们需要匹配的8-16位中间有数字而且有大写字母而且有小写字母,的时修就用到了(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z]).{8,16} 此时,我们能匹配8-16 位的数字中,必须有数字,而且有小写字母,而且有大写字母 这时,如果要被匹配的字符串中不能出现 http 这时怎么处理呢? 答案很简单 加个正向否定预搜索就可以了 (?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?!http).{8,16} 下一个实例,货币替换. 1 理清思路,货币替换对正则而言就是要找那些 距离结尾或[.] 隔着/d{3}+ 的/d 所以一开始就是(/d)(?=(/d{3})+($|/./d*)) 如果不希望回代后面的值,就用(/d)(?=(?:/d{3})+(?:$|/./d*)) 再补点预搜索条件(?=/d)(?!/./d*) 是数字,而且不能以 .开头 最后就拼接成了. (?<!/./d*)(?=/d)(/d)(?=(?:/d{3})+(?:$|/./d*)) 附PHP代码. <?PHP $money_arr = array( "0","12","123","1234","12345","123456","1234567","123456789","1234567890","12.345","123.456","1234.56","12345.6789","123456.789","1234567.89","12345678.9","sdsd12345678.9" ); foreach($money_arr as $key=>$val) { echo $val; $str = preg_replace("/(?=/d)(?!/./d*)(/d)(?=(?:/d{3})+($|/./d*))/","$1,",$val); echo "the replace result is";echo $str; echo "<hr/>"; } function pr($arr){ //格式化输出数组. print("<pre>");print_r($arr);print("</pre>"); } ?> 下一例: <img src=’xxx’> <img src=’xxx’ /> <img src=’xxx’ > ddd</img> 当需要抓取这三种时,第三种的前面和第一种重复,则用 ? 来解决 <img[^>]>(.*<//img>)? 即可