php 正则表达式总结及应用

一、正则表达式的介绍: 
    正则表达式是用于描述字符排列和匹配模式的一种语法规则。它主要用于字符串的模式分割、匹配、查找及替换操作。 
    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次 ,但尽可能少的匹配

十、中文匹配
1、UTF8汉字编码范围:0x4e00 - 0x9fa5 , 并使用u模式修正符
2、ANSI(gb2312)汉字编码范围:0xb0 - 0xf7, 0xa1 - 0xfe



  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值