php中正则表达式详解

来源:互联网 发布:vue.js权威指南 微盘 编辑:程序博客网 时间:2024/06/05 19:44

php中正则表达式详解

概述

正则表达式是一种描述字符串结果的语法规则,是一个特定的格式化模式,可以匹配、替换、截取匹配的字符串。常用的语言基本上都有正则表达式,如JavaScript、java等。其实,只有了解一种语言的正则使用,其他语言的正则使用起来,就相对简单些。文本主要围绕解决下面问题展开。

  • 有哪些常用的转义字符
  • 什么是限定符与定位符
  • 什么是单词定位符
  • 特殊字符有哪些
  • 什么是逆向引用以及怎样使用逆向引用
  • 匹配模式
  • php中怎样使用正则表达式
  • php中哪些方面需要用到正则
  • 怎样进行邮箱匹配,url匹配,手机匹配
  • 怎样使用正则替换字符串中某些字符
  • 贪婪匹配与惰性匹配区别
  • 正则表达式之回溯与固态分组
  • 正则优缺点有哪些

正则表达式的基本知识汇总

行定位符(^与$)

行定位符是用来描述字符串的边界。“$”表示行结尾“^”表示行开始如"^de",表示以de开头的字符串 "de$",表示以de结尾的字符串。

单词定界符

我们在查找的一个单词的时候,如an是否在一个字符串”gril and body”中存在,很明显如果匹配的话,an肯定是可以匹配字符串“gril and body”匹配到,怎样才能让其匹配单词,而不是单词的一部分呢?这时候,我们可以是哟个单词定界符\b。 
\ban\b 去匹配”gril and body”的话,就会提示匹配不到。 
当然还有一个大写的\B,它的意思,和\b正好相反,它匹配的字符串不能使一个完整的单词,而是其他单词或字符串中的一部分。如\Ban\B。

选择字符(|) ,表示或

选择字符表示或的意思。如Aa|aA,表示Aa或者是aA的意思。注意使用”[]”与”|”的区别,在于”[]”只能匹配单个字符,而”|”可以匹配任意长度的字符串。在使用”[]”的时候,往往配合连接字符”-“一起使用,如[a-d],代表a或b或c或d。

排除字符,排除操作

正则表达式提供了”^”来表示排除不符合的字符,^一般放在[]中。如[^1-5],该字符不是1~5之间的数字。

限定符(?*+{n,m})

限定符主要是用来限定每个字符串出现的次数。

限定字符含义?零次或一次*零次或多次+一次或多次{n}n次{n,}至少n次{n,m}n到m次

如(D+)表示一个或多个D

点号操作符

匹配任意一个字符(不包含换行符)

表达式中的反斜杠(\)

表达式中的反斜杠有多重意义,如转义、指定预定义的字符集、定义断言、显示不打印的字符。

转义字符

转义字符主要是将一些特殊字符转为普通字符。而这些常用特殊字符有”.”,”?”、”\”等。

指定预定义的字符集

字符含义\d任意一个十进制数字[0-9]\D任意一个非十进制数字\s任意一个空白字符(空格、换行符、换页符、回车符、字表符)\S任意一个非空白字符\w任意一个单词字符\W任意个非单词字符

###显示不可打印的字符

字符含义\a报警\b退格\f换页\n换行\r回车\t字表符

括号字符()

在正则表达式中小括号的作用主要有:

  • 改变限定符如(|、* 、^)的作用范围 
    如(my|your)baby,如果没有”()”,|将匹配的是要么是my,要么是yourbaby,有了小括号,匹配的就是mybaby或yourbaby。
  • 进行分组,便于反向引用

反向引用

反向引用,就是依靠子表达式的”记忆”功能,匹配连续出现的字串或是字符。如(dqs)(pps)\1\2,表示匹配字符串dqsppsdqspps。在下面php应用中,我将详细展开学习反向引用。

模式修饰符

模式修饰符的作用是设定模式,也就是正则表达式如何解释。php中主要模式如下表:

修饰符说明i忽略大小写m多文本模式s单行文本模式x忽略空白字符

正则表达式在php中应用

php中字符串匹配

所谓的字符串匹配,言外之意就是判断一个字符串中,是否包含或是等于另一个字符串。如果不使用正则,我们可以使用php中提供了很多方法进行这样的判断。

不使用正则匹配

  • strstr函数 
    string strstr ( string haystack,mixedneedle [, bool $before_needle = false ]) 
    • 注1:haystackneedle是被查找的字符串。该函数区分大小写。
    • 注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 -计算指定字符串在目标字符串中最后一次出现的位置(不区分大小写

使用正则进行匹配

在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。

实例

  • 实例1 
    判断字符串”http://blog.csdn.net/hsd2012“中是否包含csdn? 
    解法一(不适用正则): 
    如果不适用正则,我们使用strstr或者strpos中任意一个都可以,在此,我将使用strstr函数,代码如下:
$str='http://blog.csdn.net/hsd2012';function checkStr1($str,$str2){    return strstr1($str,$str2)?true:false;}echo checkStr($str,'csdn');

解法二:使用正则 
因为我们只需要判断是否存在即可,所以选择preg_match。

$str='http://blog.csdn.net/hsd2012';$pattern='/csdn/';function checkStr2($str,$str2){    return preg_match($str2,$str)?true:false;}echo checkStr2($str,$pattern);
  • 实例2(考察单词定界符) 
    判断字符串”I am a good boy”中是否包含单词go 
    首先判断是单词,而不是字符串,因此比较的时候,需要比较是否包含’ go ‘,即在字符串go前后有一个空格。 
    解析:如果使用非正则比较,只需要调用上面的checkStr1()函数即可,注意,第二个参数前后要加一个空格,即’ go ‘。如果使用正则, 
    我们可以考虑使用单词定界符\b,那么$pattern=’/\bgo\b/’;然后调用checkStr2函数即可.
  • 例3(考察反向引用
    判断字符串”I am a good boy”中是否包含3个相同的字母 
    解析:此时,如果我们不使用正则,将会很难判断,因为字母太多了,我们不可能去将所有字母分别与该字符串比较,那样工作量也比较大。这时候涉及到了正在的反向引用。在php正则表达式中,通过\n,来表示第n次匹配到的结果。如\5代表第五次匹配到的结果。那么本题的$pattern='/(\w).*\1.*\1/'; 
    主要注意的是,在使用反向匹配的时候都需要使用(),反向匹配时,匹配()里面出现的字符或字符串。

php中字符串替换

不使用正则

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

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

使用正则

如果使用正则替换,php中提供了preg_replace _callback和preg_replace 函数,preg_replace 原型如下: 
mixed preg_replace ( mixed pattern,mixedreplacement , mixed subject[,intlimit = -1 [, int &count]])subject中,查找pattern,使replacement 去替换,如果有limitlimitpregreplacecallbackpregreplacepregreplaceback使callbackreplacement.1hello,hello;:str=’hello,中国’; 
str=strreplace(hello,,str) 
或是使用str=substrreplace(str,’你好’,0,5) 
使用正则 
pattern=/hello/;str=preg_replace (pattern,,str); 
- 例2 
去除字符串”gawwenngeeojjgegop”中连续相同的字母

$str='gawwenngeeojjgegop';$pattern='/(.)\1/';$str=preg_replace($pattern,'',$str);

解析:当然这样可能会遇到,当第一次去除了重复了字符串后,又出来重复的字符串。如字符串味’gewwenngeeojjgegop’,针对这中问题,当然,这样的话,通过判断,继续替换下去。

  • 例3 
    将字符串中”age13gegep3iorji65k65k”;中出现的连续两个数字改为第二个数字,如字符串中13被改为3
$str='age13gegep3iorji65k65k';$pattern='/(\d)(\d)/';$str=preg_replace($pattern,'$2', $str);

解析:$n在正则表达式外使用反向引用。n代表第几次匹配到的结果。

php中字符串分割

不适用正则

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 ]] )

  • 例题 
    将字符串 ‘http://blog.csdn.net/hsd2012/article/details/51152810‘按照’/’进行分割 
    解法一:
$str='http://blog.csdn.net/hsd2012/article/details/51152810';$str=explode('/', $str);

解法二:

$str='http://blog.csdn.net/hsd2012/article/details/51152810';$pattern='/\//';  /*因为/为特殊字符,需要转移*/$str=preg_split ($pattern, $str);

php中贪婪匹配与惰性匹配

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

php正则表达式之回溯与固态分组

回溯

首先我们需要清楚什么是回溯,回溯就像是在走岔路口,当遇到岔路的时候就先在每个路口做一个标记。如果走了死路,就可以照原路返回,直到遇见之前所做过的标记,标记着还未尝试过的道路。如果那条路也走不能,可以继续返回,找到下一个标记,如此重复,直到找到出路,或者直到完成所有没有尝试过的路。首先我们看例题

$str='aageacwgewcaw';$pattern='/a\w*c/i';$str=preg_match($pattern, $str);

看到上面的程序,可能都清楚是什么意思,就是匹配$str是否包含这样一个由”a+0个或多个字母+c”不区分大小写的字符串。但是至于程序怎样去匹配的呢?匹配的过程中,回溯了多少次呢?

匹配过程接下来操作描述‘a\w*c’中a匹配到’aageacwgewcaw’中第一个字符a\w进行下一个字符匹配因为\w是贪婪匹配,会一直匹配到’aageacwgewcaw’中最后一个字符wc进行下一个字符匹配时‘a\w*c’中c发现没有可以匹配的于是\w匹配进行第一次回溯,匹配到倒数第二个字符a‘a\w*c’中c发现还是没有可以匹配的于是\w匹配进行第二次回溯,匹配到倒数第三个字符c‘a\w*c’中c匹配成功匹配结束返回结果

现在,如果我们将patternpattern=’/a\w*?c/i’;又会回溯多少次呢?正确答案是回溯四次。

固态分组

固态分组,目的就是减少回溯次数, 使用(?>…)括号中的匹配时如果产生了备选状态,那么一旦离开括号便会被立即 引擎抛弃掉。举个典型的例子如: ‘\w+:’这个表达式在进行匹配时的流程是这样的,会优先去匹配所有的符合\w的字符,假如字符串的末尾没有’:’,即匹配没有找到冒号,此时触发回溯机制,他会迫使前面的\w+释放字符,并且在交还的字符中重新尝试与’:’作比对。但是问题出现在这里: \w是不包含冒号的,显然无论如何都不会匹配成功,可是依照回溯机制,引擎还是得硬着头皮往前找,这就是对资源的浪费。所以我们就需要避免这种回溯,对此的方法就是将前面匹配到的内容固化,不令其存储备用状态!,那么引擎就会因为没有备用状态可用而只得结束匹配过程。大大减少回溯的次数。 
如下代码,就不会进行回溯:

$str='nihaoaheloo';$pattern='/(?>\w+):/';$rs=preg_match($pattern, $str);

当然有的时候,又需慎用固态分组,如下,我要检查$str中是否包含以a结尾的字符串,很明显是包含的,但是因为使用了固态分组,反而达不到我们想要的效果

$str='nihaoahelaa';$pattern1='/(?>\w+)a/';$pattern2='/\w+a/';$rs=preg_match($pattern1, $str);//0$rs=preg_match($pattern2, $str);//1

php中其他常用字符串操作函数

  • 字符串截取截取 
    string substr ( string string,intstart [, int length])stringmbsubstr(stringstr , int start[,intlength = NULL [, string $encoding = mb_internal_encoding() ]] )
  • 字符串中大小写转换 
    strtoupper 
    strtolower 
    ucfirst 
    ucwords
  • 字符串比较 
    -strcmp、strcasecmp、strnatcmp
  • 字符串过滤
  • 字符串翻转 
    strrev($str);
  • 字符串随机排序 
    string str_shuffle ( string $str )

补充

怎样进行邮箱匹配,url匹配,手机匹配

使用preg_match函数进行匹配,以下内容从TP中复制而来。 
邮箱验证 
pattern=/\w+([+.]\w+)@\w+([.]\w+)\.\w+([.]\w+)/’; 
url匹配 
pattern='/^http(s?):\/\/(?:[A-za-z0-9-]+\.)+[A-za-z]{2,4}(:\d+)?(?:[\/\?#][\/=\?%\-&~`@[\]\':+!\.#\w]*)?/’; 
手机验证 
pattern=/1[3458]\d10/’;

php中正则的优缺点

php中正则在某些时候,能帮我们解决php函数很多困难的匹配或是替换。然后php中正则的效率,往往是我们需要考虑的,所以在某些时候,能不用正则还是尽量不去用它,除非,某些场合必须用到,或是我们能够有效减少其回溯次数。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝禁止评价一个月怎么办 被卖家电话骚扰怎么办 恶意骚扰扣12分怎么办 新店开张交保证金被骗了怎么办 支付宝蚂蚁花呗逾期怎么办 被注销的微信怎么办 花呗有些不能用怎么办 实体店生意不好做怎么办 电器实体店生意越来越差怎么办 开业第一天不吉利怎么办 美容店开业第一天没人怎么办 淘宝店铺没有人访问怎么办 淘宝店铺没有人问怎么办 淘宝申请退款后店铺关闭怎么办 宝贝详情怎么改不了怎么办 改详情页后被删除宝贝怎么办 淘宝网商贷生意不好还不了怎么办 英国遗失在酒店物品怎么办 班福法则首位是0怎么办 同事能力比你强怎么办 新买的木板床响怎么办 笔记本键盘驱动坏了怎么办 云柜快递超时了怎么办 毕业设计被老师发现抄的怎么办 地板颜色太深了怎么办 皮质鞋子破皮了怎么办 吃了蜘蛛丝会怎么办 南京高二分班不公平怎么办? 高中分班考试没考好怎么办 实木门上的伸缩缝太深怎么办 mac点关机没反应怎么办 被压倒扁的易拉罐怎么办 白色车漏底漆了怎么办 客厅对着卧室门怎么办 老公不上进还懒怎么办 二胡按弦手指分不开怎么办 酷塑做完后疼痛怎么办 冷冻治疗后水泡破了怎么办 冷冻治疗的水泡破了怎么办? 冷冻治疗水泡破了怎么办 脚上冷冻后起泡怎么办