php 正则表达式总结及应用

来源:互联网 发布:linux mint 中文 编辑:程序博客网 时间:2024/05/17 05:07
一、正则表达式的介绍: 
    正则表达式是用于描述字符排列和匹配模式的一种语法规则。它主要用于字符串的模式分割、匹配、查找及替换操作。 
    1. 用途:匹配、查找、替换、分割 
    2. php提供了两套正则表达式函数库 
        *1. Perl 兼容正则表达式函数(推荐使用) 
        2. POSIX 扩展正则表达式函数

二、 语法: 
    1. 表达式的格式: "/表达式/[修正符]" 
        解释:其中"/"表示正则表达式的定界符,但是也可以是其他符号:如”#“,”!“ 
                注意:定界符不可以是字母、数字和斜线\。 
                像“#”、“|”、“!”等都可以的 
                如:/.../   #...#  |....| 
        其中修正符是可选的,表示对表达式做额外的修饰。

三、组成部分
1、原子
> 单个字符、数字,如a-z,A-Z,0-9。 > 模式单元,如(ABC)为由多个原子组成的大的原子。 > 原子表,如 [ABC]。 > 重新使用的模式单元,如:\\1 > 普通转义字符,如:\d, \D, \w > 转义元字符,如:\*,\. > 元字符


2、定界符
通常使用“/”作为定界符开始和结束。也可以使用“#”,而使用“#”的另一个作用就是当字符串中有很多“/”字符时,就不需要对其转义,比如uri

通常在使用preg_match的结果数组第0个将包含与整个匹配的字符串

//使用定界符“/”<?php$regex = '/^http:\/\/([\w.]+)\/([\w]+)\/([\w]+)\.html$/i';$str = 'http://www.youku.com/show_page/id_1234.html';$matches = array();if(preg_match($regex, $str, $matches)){    var_dump($matches);}//结果array (size=4)  0 => string 'http://www.youku.com/show_page/id_1234.html' (length=46)  1 => string 'www.youku.com' (length=13)  2 => string 'show_page' (length=9)  3 => string 'id_1234' (length=10)  //使用定界符“#”  <?php$regex = '#^http://([\w.]+)/([\w]+)/([\w]+)\.html$#i';$str = 'http://www.youku.com/show_page/id_1234.html';$matches = array();if(preg_match($regex, $str, $matches)){    var_dump($matches);}//结果array (size=4)  0 => string 'http://www.youku.com/show_page/id_1234.html' (length=43)  1 => string 'www.youku.com' (length=13)  2 => string 'show_page' (length=9)  3 => string 'id_1234' (length=7)


3、修饰符
3.1、不区分大小写
正则表达式最后一个"i"就是修饰符,表示忽略大小写进行匹配
 <?php$regex = '/HELLO/';$str = 'hello';$matches = array();if(preg_match($regex, $str, $matches)){    echo 'No i=>Valid Successful!',"\n";}$regex = '/HELLO/i';if(preg_match($regex, $str, $matches)){    echo 'YES i=>Valid Successful!',"\n";}//结果YES i=>Valid Successful!

3.2、忽略空格
如果最后一位位"x"表示忽略空格
3.3、"s"表示匹配视为单行(就是可以让点.支持换行) 


3.4、"U"拒绝贪婪匹配


4、 元字符(具有特殊意义字符): 
[] 表示单个字符的原子表 例如:[aoeiu] 表示任意一个元音字母  [0-9] 表示任意一位数字  [a-z][0-9]表示小写字和一位数字构成的两位字符  [a-zA-Z0-9] 表示任意一位大小字母或数字 [^] 表示除中括号内原子之外的任何字符 是[]的取反 例如:[^0-9] 表示任意一位非数字字符  [^a-z] 表示任意一位非小写字母 {m}    表示对前面原子的数量控制,表示是m次 例如:[0-9]{4} 表示4为数字  [1][3-8][0-9]{9} 手机号码 {m,} 表示对前面原子的数量控制,表示是至少m次          例如: [0-9]{2,} 表示两位及以上的数字 {m,n}表示对前面原子的数量控制,表示是m到n次 例如: [a-z]{6,8} 表示6到8位的小写字母 * 表示对前面原子的数量控制,表示是任意次,等价于{0,} + 表示对前面原子的数量控制,表示至少1次,等价于{1,} ? 表示对前面原子的数量控制,表示0次或1次(可有可无) 等价于{0,1} 例如:正整数:[1-9][0-9]* 整数:[\-]?[0-9]+ () 表示一个整体原子,【还有一个子存储单元的作用】。 也可以使用?:来拒绝子存储。 (?:.*?) 例如:(red) 字串red   (rea|blue) 字串red或blue   (abc){2} 表示两个abc |  表示或的意思 (rea|blue) 字串red或blue ^  用在正则单元块的开头处,表示必须以指定的开头 $  用在正则单元块的结尾处,表示必须以指定的结尾 .  表示任意一个除换行符之外的字符 常用组合: .*?  表示最小匹配所有字符(拒绝贪婪匹配) 


5、普通转义字符
\d 匹配一个数字;等价于[0-9]\D 匹配除数字以外任何一个字符;等价于[^0-9]\w 匹配一个英文字母、数字或下划线;等价于[0-9a-zA-Z_]\W 匹配除英文字母、数字和下划线以外任何一个字符;等价于[^0-9a-zA-Z_] \s 匹配一个空白字符;等价于[\f\n\r\t\v] \S 匹配除空白字符以外任何一个字符;等价于[^\f\n\r\t\v]\oNN 匹配一个八进制数字 \xNN 匹配一个十六进制数字\cC 匹配一个控制字符 ####不可打印显示的字符####\a 报警 等价于 0x07\b 退格 等价于 0x08\f 匹配一个换页符等价于 \x0c 或 \cL\n 匹配一个换行符;等价于 \x0a 或 \cJ \r 匹配一个回车符等价于\x0d 或 \cM\t 匹配一个制表符;等价于 \x09\或\cl \v 匹配一个垂直制表符;等价于\x0b或\ck 



四、预查
4.1、断言某些字符串中某些字符的存在与否,它分为两种
正向预查:(?=) 相对应的 (?!)表示否定意思
反向预查:(?<=) 相对应的 (?<!)表示否定意思
<?php$regex = '/(?<=c)d(?=e)/';  /* d 前面紧跟c, d 后面紧跟e*/$str = 'abcdefgk';$matches = array();if(preg_match($regex, $str, $matches)){    var_dump($matches);}//结果d<?php$regex = '/(?<!c)d(?!e)/';  /* d 前面不紧跟c, d 后面不紧跟e*/$str = 'abcdefgk';$matches = array();if(preg_match($regex, $str, $matches)){    var_dump($matches);}else{    var_dump('no match');}//结果no match


4.2、字符宽度判断
匹配的时候只做一个判断,本身是不占位置的。
/HE(?=L)LLO/ 与HELLO匹配,
而/HE(?=L)LO/与HELLO是不匹配的。毕竟但从字节数上两者就是不匹配的,前者只有4个,而后者有5个。

五、捕获数据
5.1、没有指明类型而进行的分组,将会被获取,供以后使用。
> 指明类型指的是通配符。所以只有圆括号起始位置没有问号的才能被捕捉。


> 在同一个表达式内的引用叫做反向引用。
> 调用格式: \编号(如\1)。
<?php$regex = '/^(Chuanshanjia)[\w\s!]+\1$/';$str = 'Chuanshanjia thank Chuanshanjia';$matches = array();if(preg_match($regex, $str, $matches)){    var_dump($matches);}//运行结果array (size=2)  0 => string 'Chuanshanjia thank Chuanshanjia' (length=31)  1 => string 'Chuanshanjia' (length=12)

  
5.2、捕获组
5.2.1、pattern模式,也是常用的捕获模式
<?php$regex = '/(ab(c)+)+d(e)?/';$str = 'abccde';$matches = array();if(preg_match($regex, $str, $matches)){    print_r($matches);}//结果Array ( [0] => abccde [1] => abcc [2] => c [3] => e )


5.2.2、?P<name>pattern 模式,通过设置的name直接快速调用结果
<?php$regex = '/(?P<group1>\w(?P<group2>\w))abc(?P<group3>\w)45/';$str = 'fsabcd45';$matches = array();if(preg_match($regex, $str, $matches)){    print_r($matches);}//结果Array ( [0] => fsabcd45 [group1] => fs [1] => fs [group2] => s [2] => s [group3] => d [3] => d )


5.2.3、\num 捕获,是对捕获组的反向引用。  例如\2表示第二个子组匹配值,\表示第一个子组匹配值
<?php$regex = '/(\w)(\w)\2\1/';$str = 'abba';$matches = array();if(preg_match($regex, $str, $matches)){    print_r($matches);}//结果Array ( [0] => abba [1] => a [2] => b )


5.2.4、\k< name > 是对命名捕获组的反向引用。其中 name 是捕获组名。
<?php$regex='/(?P<name>\w)abc\k<name>/';$str="fabcf";preg_match_all($regex, $str,$matches);print_r($matches);//结果Array ( [0] => Array ( [0] => fabcf ) [name] => Array ( [0] => f ) [1] => Array ( [0] => f ) )


5.3、非捕获组(?:pattern)
与(pattern)的唯一区别是,匹配pattern但不捕获匹配结果

六、懒性匹配
格式:限定符?
原理:"?":如果前面有限定符,会使用最小的数据。如“*”会取0个,而“+”会取1个,如过是{3,5}会取3个
<?php$regex = '/heL*/i';$str = 'heLLLLLLLLLLLLLLLL';if(preg_match($regex, $str, $matches)){    var_dump($matches);}//heLLLLLLLLLLLLLLLL$regex = '/heL*?/i';$str = 'heLLLLLLLLLLLLLLLL';if(preg_match($regex, $str, $matches)){    var_dump($matches);}//he$regex = '/heL+?/i';$str = 'heLLLLLLLLLLLLLLLL';if(preg_match($regex, $str, $matches)){    var_dump($matches);}//heL$regex = '/heL{3,10}?/i';$str = 'heLLLLLLLLLLLLLLLL';if(preg_match($regex, $str, $matches)){    var_dump($matches);}//heLLL


七、注释
格式:(?# 注释内容)
用途:主要用于复杂的注释
<?php$regex = '/    ^host=(?<!\.)([\d.]+)(?!\.)                 (?#主机地址)\|    ([\w!@#$%^&*()_+\-]+)                       (?#用户名)\|    ([\w!@#$%^&*()_+\-]+)                       (?#密码)(?!\|)$/ix';$str = 'host=192.168.10.221|root|123456';$matches = array();if(preg_match($regex, $str, $matches)){    var_dump($matches);}//结果array (size=4)  0 => string 'host=192.168.10.221|root|123456' (length=31)  1 => string '192.168.10.221' (length=14)  2 => string 'root' (length=4)  3 => string '123456' (length=6)

  

 八、php 中应用正则表达式

preg_grep --  返回与模式匹配的数组单元     * preg_match_all -- 进行全局正则表达式匹配 , 返回共计匹配的个数。         和下面的一样,不同的是匹配到最后(全局匹配)     * preg_match -- 进行正则表达式匹配,只匹配一次,返回1,否则0,         格式:preg_match("正则表达式","被匹配的字串",存放结果的变量名,PREG_OFFSET_CAPTURE,起始偏移量)         其中:PREG_OFFSET_CAPTURE表示获取匹配索引位置               起始偏移量:从指定位置开始匹配 preg_quote -- 转义正则表达式字符 preg_split -- 用正则表达式分割字符串 preg_replace -- 执行正则表达式的搜索和替换

8.1、查找

8.1.1、不使用正则表达式

strstr函数 string strstr ( string haystack,mixedneedle [, bool $before_needle = false ]) 注1:haystack是当事字符串,needle是被查找的字符串。该函数区分大小写。注2:返回值是从needle开始到最后。注3:关于$needle,如果不是字符串,被当作整形来作为字符的序号来使用。注4:before_needle若为true,则返回前东西。stristr函数与strstr函数相同,只是它不区分大小写strpo函数 int strpos ( string haystack,mixedneedle [, int $offset = 0 ] ) 注1:可选的 offset 参数可以用来指定从 haystack 中的哪一个字符开始查找。返回的数字位置是相对于 haystack 的起始位置而言的。stripos -查找字符串首次出现的位置(不区分大小定)strrpos -计算指定字符串在目标字符串中最后一次出现的位置strripos -计算指定字符串在目标字符串中最后一次出现的位置(不区分大小写)

8.1.2、使用正则表达式

在php中,提供了preg_math()和preg_match_all函数进行正则匹配

int preg_match|preg_match_all ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )搜索subject与pattern给定的正则表达式的一个匹配. pattern:要搜索的模式,字符串类型。 subject :输入字符串。 matches:如果提供了参数matches,它将被填充为搜索结果。 matches[0]将包含完整模式匹配到的文本,matches[1]将包含第一个捕获子组匹配到的文本,以此类推。 flags:flags可以被设置为以下标记值:PREG_OFFSET_CAPTURE 如果传递了这个标记,对于每一个出现的匹配返回时会附加字符串偏移量(相对于目标字符串的)。 注意:这会改变填充到matches参数的数组,使其每个元素成为一个由 第0个元素是匹配到的字符串,第1个元素是该匹配字符串 在目标字符串subject中的偏移量。 offset:通常,搜索从目标字符串的开始位置开始。可选参数 offset 用于 指定从目标字符串的某个未知开始搜索(单位是字节)。 返回值:preg_match()返回 pattern 的匹配次数。 它的值将是0次(不匹配)或1次,因为 preg_match()在第一次匹配后 将会停止搜索。 preg_match_all()不同于此,它会一直搜索subject直到到达结尾。 如果发生错误 preg_match()返回 FALSE。

案例一:判断url是否包含csdn

$str='http://blog.csdn.net/hsd2012';$pattern='/csdn/';var_dump(preg_match($pattern,$str));//结果,表示查到1 
案例二:判断字符串”I am a good boy”中是否包含单词go

<?php//判断字符串”I am a good boy”中是否包含单词go$str='I am a good boy, go go';$pattern='/\bgo\b/';//单词限定符var_dump(preg_match($pattern,$str, $matches));//结果为1,表示有找到单词 go

案例三:判断字符串”I am a good boy”中是否包含3个相同的字母 

<?php$str='I am a good boy';$pattern='/(\w).*\1.*\1/';preg_match($pattern,$str, $matches);var_dump($matches);//结果array (size=2)  0 => string 'ood bo' (length=6)  1 => string 'o' (length=1)

8.2、替换

8.2.1、不使用正则替换

php中当替换字符串的时候,如果不适用正则,我们通常使用substr、mb_substr、str_replace、substr_replace关于这几个函数

str_replace(find,replace,string,count)str_replace(find,replace,string,count)使用一个字符串替换字符串中的另一些字符find 必需。规定要查找的值。replace 必需。规定替换 find 中的值的值。string 必需。规定被搜索的字符串。count 可选。一个变量,对替换数进行计数。substr_replace(string,replacement,start,length)把字符串的一部分替换为另一个字符串。适合用于替换自定位置的字符串。string 必需。规定要检查的字符串。replacement 必需。规定要插入的字符串。start 必需。规定在字符串的何处开始替换。

8.2.2、使用php中提供了preg_replace _callback和preg_replace 函数

mixed preg_replace ( mixed pattern,mixed replacement , mixed subject[,intlimit = -1 [, int &count]])函数功能描述:在字符串subject中,查找pattern,然后使用replacement 去替换,如果有limit则代表限制替换limit次。pregreplacecallback与pregreplace功能相识,不同的是pregreplaceback使用一个回调函数callback来代替replacement

案例一:将字符串”hello,中国”中的hello替换为′你好′

如果不是用正则:str=’hello,中国’; str=str_replace(′hello′,′你好′,str) 或是使用str=substr_replace(str,’你好’,0,5) 使用正则 pattern=′/hello/′;str=preg_replace (pattern,′你好′,str); 


案例二:去除字符串”abbbcvdfddddereeefefghgghjg”中连续相同的字母
<?php$str='abbbcvdfddddereeefefghgghjg';$pattern='/(.)\1/';$str=preg_replace($pattern,'',$str);var_dump($str);//abcvdferefefghhjg

案例三:将字符串中”abc45gfegeedp3iorfe67k321k”;中出现的连续两个数字改为第二个数字,如字符串中13被改为3

<?php$str='abc45gfegeedp3iorfe67k321k';$pattern='/(\d)(\d)/';$str=preg_replace($pattern,'$2', $str);var_dump($str);//abc5gfegeedp3iorfe7k21k
解析:$n在正则表达式外使用反向引用。n代表第几次匹配到的结果


8.3、分割

php提供了explode函数去分割字符串,与其对应的是implode。关于explode原型如下: array explode ( string delimiter,stringstring [, int $limit ] ) delimiter:边界上的分隔字符。 string:输入的字符串。 limit:如果设置了 limit 参数并且是正数,则返回的数组包含最多 limit 个元素,而最后那个元素将包含 string 的剩余部分。如果 limit 参数是负数,则返回除了最后的 -limit 个元素外的所有元素。如果 limit 是 0,则会被当做 1。

关于通过正则表达式进行字符串分割,php提供了split、preg_split 函数。preg_split() 函数,通常是比 split() 更快的替代方案。 array preg_split ( string pattern,stringsubject [, int limit=−1[,intflags = 0 ]] )

<?php$str='http://127.0.0.1/linux/webApi/test.php';$str=explode('/', $str);var_dump($str);//结果array (size=6)  0 => string 'http:' (length=5)  1 => string '' (length=0)  2 => string '127.0.0.1' (length=9)  3 => string 'linux' (length=5)  4 => string 'webApi' (length=6)  5 => string 'test.php' (length=8)$str='http://127.0.0.1/linux/webApi/test.php';$pattern='/\//';  /*因为/为特殊字符,需要转移*/$str=preg_split ($pattern, $str);var_dump($str);//结果0 => string 'http:' (length=5)  1 => string '' (length=0)  2 => string '127.0.0.1' (length=9)  3 => string 'linux' (length=5)  4 => string 'webApi' (length=6)  5 => string 'test.php' (length=8)

九、php中贪婪匹配与惰性匹配

贪婪匹配:就是匹配尽可能多的字符。 比如,正则表达式中m.*n,它将匹配最长以m开始,n结尾的字符串。如果用它来搜索manmpndegenc的话,它将匹配到的字符串是manmpndegen而非man。可以这样想,当匹配到m的时候,它将从后面往前匹配字符n。
懒惰匹配:就是匹配尽可能少的字符。 有的时候,我们需要并不是去贪婪匹配,而是尽可能少的去匹配。这时候,就需要将其转为惰性匹配。怎样将一个贪婪匹配转为惰性匹配呢?只需要在其后面添加一个”?”即可。如m.*?n将匹配manmpndegenc,匹配到的字符串是man。*?零次或多次,但尽可能少的匹配+?一次或多次,但尽可能少的匹配??0次或1次,但尽可能少的匹配{n,}?至少n次,但尽可能少的匹配{n,m}?n到m次 ,但尽可能少的匹配




原创粉丝点击