PHP-正则表达式

世界上最难懂的是道士的鬼符、医生的处方和程序员的正则表达示。(ง •_•)ง


PHP 正则表达式


正则表达示我们其实之前经常看到,它主要用在以下一些地方:
1.匹配邮箱、手机号码、验证码
2.替换敏感的关键词。例如:涉及政治和骂人的话
3.文章采集。
4.早期的表情替换技术,ubb文件编码、markdown编辑器替换等
5.以后自己写模板引擎也需要用到正则表达示
其他….

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



1. 定界符

定界符,就是定一个边界,边界以内的就是正则表达示。
PHP的正则表达示定界符的规定如下:
定界符,不能用a-zA-Z0-9\ 其他的都可以用。必须成对出现,有开始就有结束。
我们来例几个例子:
例子 说明
/中间写正则/ 正确
$中间写正则$ 正确
%中间写正则% 正确
^中间写正则^ 正确
@中间写正则@ 正确
#中间写正则# 正确
(中间写正则) 错误
A中间写正则A 错误


2. 转义字符

注:\ 是转义字符,如果在以后正则表达示里面需要匹配/,如下:
/ / /
这个时候真要匹配/ 的时候,需要把定界符里面的/ 用转义字符转义一下,写成下面的例子:
/ \/ /
如果你觉得麻烦,遇到这种需要转义的字符的时候可以把两个正斜线(/ /)定界,改为其他的定界符(# #)。


3. 原子

原子是正则表达示里面的最小单位,原子说白了就是需要匹配的内容。一个成立的正则表达示当中必须最少要有一个原子。
所有可见不可见的字符就是原子!
说明:我们见到的空格、回车、换行、0-9、A-Za-z、中文、标点符号、特殊符号全为原子。
在做原子的实例前我们先来讲解一个函数,preg_match:
int preg_match ( string $正则 , string $字符串 [, array &$结果] )
功能:根据$正则变量,匹配$字符串变量。如果存在则返回匹配的个数,把匹配到的结果放到$结果变量里。如果没有匹配到结果返回0。
注:上面是preg_match常用的主要几个参数。我在上面将另外几个参数没有列出来。因为,另外两个参数太不常用了。
我们来通过实验来证明:
(1)↓↓
<?php
//定义一个变量叫zz,放正则表达示。为了方便大家记忆,如果你英文比较ok,建议把变量名还是写成
//英文的$pattern$zz = '/a/';
$string = 'ddfdjjvi2jfvkwkfi24';
if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

因为我希望的是匹配a,而$string当是是不存在a的,所以不成功。

(2)↓↓
<?php
$zz = '/wq/';
$string = 'ssssswqaaaaaa';
if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

上面的字符串中s后存在wq,因此匹配成功。

接下来我们匹配一个空格试试:

(3)↓↓
<?php
$zz = '/ /';
$string = 'sssssw aaaaa';
if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

运行结果:
匹配到了,结果为:array(1) { [0]=> string(1) " " }

因上,$string这个变量的w字符后存在一个空格。所以匹配成功,输出了字符串类型,长度为1。只不过我们的肉眼不可见,看不到这个字符串而已。

4. 特殊标识的原子

原子 说明 等价式
\d 匹配一个0-9 [a-zA-Z0-9_]
\D 除了0-9以外的所有字符 [^a-zA-Z0-9_]
\w a-zA-Z0-9_ [0-9]
\W 除了0-9A-Za-z_以外的所有字符 [^0-9]
\s 匹配所有空白字符\n \t \r 空格 [ \t\n\f\r]
\S 匹配所有非空白字符 [^ \t\n\f\r]
[ ] 指定范围的原子
这个个需要记住,最好达到默写级别。记忆的时候成对记忆,\d是匹配一个0-9,那么\D 就是除了0-9以外的所有字符。上面已经说明的很清楚了,我们进行实验一步一步对这些进行学习。

1. \d匹配一个0-9
<?php
$zz = '/\d/';

$string = '我爱喝9你爱不爱喝';

if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

2. \D匹配一个非0-9的值
<?php
$zz = '/\D/';

$string = '121243中23453453';

if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

运行结果:
匹配成功,匹配到了中。因为它不是0-9之间的字符。

3. \w匹配一个a-zA-Z0-9_
<?php
$zz = '/\w/';

$string = '新中_国万岁呀万岁';

if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

运行结果:
匹配成功,匹配到了下划线。

4. \W匹配一个非a-zA-Z0-9_
<?php
$zz = '/\w/';

$string = 'afasABCWEQR44231284737';

if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

运行结果:
匹配失败。因为,上面上面全是a-zA-Z0-9_,没有非a-zA-Z0-9_。

5. \s 匹配所有空白字符\n \t \r 空格
<?php
$zz = '/\s/';

$string = "中国万
岁";

if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

运行结果:
匹配成功,因为有一个回车。

6. \S 非空字符
<?php
$zz = '/\s/';

$string = "        
         a       ";

if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

运行结果:
匹配成功。虽然上面有空格,回车和缩进。但是,有一个非空白字符a。因此,匹配成功。

7. [] 指定范围的原子
<?php

$zz = '/[0-5]\w+/';

$string = '6a';

$string1 = '1C';

if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

结论:
上例中0-5匹配$string失败,而$string1成功。因为,$string中的第一个数值为6,不在[0-5]的范围之内。

<?php

$zz = '/[a-zA-Z0-9_]\w/';

$string = 'ab';

$string1 = '9A';

if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

结论:$string和$string1都匹配成功。因为\w就是[a-zA-Z0-9_]

<?php

$zz = '/[abc]\d+/';

$string = 'a9';

$string1 = 'b1';

$string2 = 'c5';

$string3 = 'd4';


if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

结论:$string、$string1、$string2匹配成功,而$string3不成功。因为$string3超过了[abc]的范围,它是从d开始的。

8. [\^ 字符] 不匹配指定区间的字符
<?php

$zz = '/[^0-9A-Za-z_]/';

$string = 'aaaaab311dd';

$string1 = '!$@!#%$#^##';

if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}

?>

结论:

  1. 匹配$string不成功,但是匹配$string1的时候成功。因为中括号里面有个抑扬符。
  2. ^ 抑扬符在中括号里面的作用是不准以中括号里面的字符进行匹配。

5. 元字符

抛出问题:\d 代表匹配一个字符。而我现在想要匹配十个八个,任意多个数字肿么办?
这个时候我们就要用到元字符。在使用原子的时候,发现只能够匹配一个字符,可是要匹配多个字符就出现了问题。
这个时候,我们需要借助元字符来帮我们修饰原子,实现更多的功能。
元字符 功能说明
* 是代表匹配前面的一个原子,匹配0次或者任意多次前面的字符。
+ 匹配一次或多前前面的一个字符
? 前面的字符可有可无【可选】 有或没有
. 更标准一些应该把点算作原子。匹配除了\n以外的所有字符
或者。注:它的优先级最低了。
^ 必须要以抑扬符之后的字符串开始
$ 必须要以$之前的字符结尾
\b 词边界
\B 非边界
{m} 有且只能出现m次
{n,m} 可以出现n到m次
{m,} 至少m次,最大次数不限制
() 改变优先级或者将某个字符串视为一个整体,匹配到的数据取出来也可以使用它

1. + 匹配最少1次前面的字符
<?php
$zz = '/\d+/';

$string = "迪奥和奥迪250都是我最爱";

//待会儿再试试中间没有0-9的情况
//$string = "迪奥和奥迪都是我最爱";


if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

运行结果:
匹配成功,证明了\d+中的+。\d是匹配数字,而+是最少匹配一次前面的字符。

2. * 匹配0次或者任意多次前面的字符
<?php
$zz = '/\w*/';

$string = "!@!@!!@#@!$@#!";

//待会儿再试试中间没有0-9的情况
//$string1 = "!@#!@#!abcABC#@#!";


if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

说明,注释掉的$string1和$string都匹配成功了。因为,\w是匹配的0-9A-Za-z_,而*是说明前面的\w可以不存在。如果存在可以有1个或者多个。

3. ? 前面的字符出现0次或者1次,可有可无
<?php

$zz = '/ABC\d?ABC/';

$string = "ABC1ABC";

//待会儿再试试中间没有0-9的情况
//$string1 = "ABC888888ABC";
//$string2 = "ABCABC";


if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

匹配$string,$string2成功,但是匹配$string1失败。
因为匹配前后都是ABC,中间是一个0-9。0-9可有可无,但是不能有多个。

4. . (点) 匹配除\n以外的所有字符
<?php

$zz = '/gg.+gg/';

$string = "ABC1ABC";


if(preg_match($zz, $string, $matches)){
   echo '匹配到了,结果为:';
   var_dump($matches);
}else{
   echo '没有匹配到';
}
?>

匹配$string,$string2成功,但是匹配$string1失败。
因为匹配前后都是ABC,中间是一个0-9。0-9可有可无,但是不能有多个。

5. |(竖线),或者,优先级最低

我们通过实验来看优先级和或者的匹配

<?php

$zz = '/abc|bcd/';

$string1 = "abccd";
$string2 = "ggggbcd";

if (preg_match($zz, $string1, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

我们来看看:
1.最开始我匹配的想法是想匹配的是abccd或者是abbcd。可是,匹配$string1和$string2,匹配出来的结果却是abc和bcd.
2.实现了或者匹配,匹配出来了abc或者是bcd。它还没有字符串连续在一起的优先级高。

那么问题来了,我要匹配上例中的abccd或者是abbcd怎么办?

需要使用到()来改变优先级。
<?php

$zz = '/ab(c|b)cd/';

$string1 = "起来abccd阅兵";
$string2 = "ggggbcd";
$string3 = '中国abbcd未来';

if (preg_match($zz, $string1, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

运行结果:
匹配到了,结果为:array(2) { [0]=> string(5) "abccd" [1]=> string(1) "c" }

结论:
1.确实匹配了了abccd或者abbcd($string1 or $string3)。
2.但是匹配的数组里面多了一个元素,这个元素的下标为1
3.()中的内容只要匹配成功,会把匹配到的数据放到下标为1的这个数组元素中。

6. ^ (抑扬符),必须要以^之后的字符串开始
<?php

$zz = '/^猪哥好帅\w+/';

$string1 = "猪哥好帅abccdaaaasds";
//$string2没有以猪哥好帅开始
$string2 = "帅abccdaaaasds";


if (preg_match($zz, $string1, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

通过实验发现以下结论:
1.$string1匹配成功,$string2没有匹配成功
2.因为$string1是以指定的字符开始的
3.而$string2并没有以^之后的字符开始
4.翻译这个正则的意思就是:以要猪哥好帅开始后面接a-zA-Z0-9_最少一个字符。

7. $ (美元符)必须要以$之前的字符结束
<?php

$zz = '/\d+努力$/';

$string1 = "12321124333努力";
//$string2
$string2 = "12311124112313力";


if (preg_match($zz, $string1, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

我们运行一下看一下结果,得出来的结论:
1.$string1 匹配成功,而$string2匹配不成功
2.$之前的字符是\d+,后面接着中文的努力。
3.因此,匹配的是这一个整体。\d指的是0-9的整型,+号代表最少一个0-9

8. \b和\B 词边界和非词边界

我们来讲解什么是边界:

1.正则表达示是有边界的,这个边界是定界符的开始和结尾是正则的边界。

2.this是一个英文单词,后面加上一个空格,意味着这个词结束了,到达了这个词的边界

\b词边界,就是指必须要在最前或者最后。
\B非边界,就是不能在一个正则表达示的最前或者最后。

<?php

$zz = '/\w+\b/';

$string1 = "this is a apple";
$string2 = "thisis a apple";
$string3 = "thisisaapple";

if (preg_match($zz, $string1, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

结论:
1.$string1、$string2和$string3都匹配成功。
2.$string1匹配的时候this 空格是边界
3.$string2匹配的时候thisis是边界
4.$string3匹配的时候,thisisaapple到了整个正则表达示的最后,因此也是边界。所以匹配成功。

我们来实验一下非词边界:

<?php

$zz = '/\Bthis/';

$string1 = "hellothis9";

//$string2 = "hello this9";
//$string2 = "this9中国万岁";

if (preg_match($zz, $string1, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

总结:
1.匹配$string1成功而$string2不成功。
2.因为\B后接的是this,所以this不能在词边界(空格和开始结尾)的位置出现。

9. {m}有且只能出现m次
<?php

$zz = '/喝\d{3}酒/';

$string1 = "喝988酒";

//$string2 = "喝98811酒";

if (preg_match($zz, $string1, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

结论:
上例中\d{3}我规定了0-9只能出现3次,多一次少一次都不行。

10. {n,m} 可以出现n到m次
<?php

$zz = '/喝\d{1,3}酒/';

$string1 = "喝9酒";

//$string2 = "喝988酒";

if (preg_match($zz, $string1, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

结论:
上例中\d{1,3}我规定了0-9只能出现1次,2次或者3次。其它次数都是错的

11. {m,} 至少m次,最大次数不限制
<?php

$zz = '/喝\d{2,}/';

$string1 = "喝9";

//$string2 = "喝98";
//$string3 = "喝98122121";


if (preg_match($zz, $string1, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

结论:
上例中\d{2,}我规定喝后面的0-9最少出现两次,最多次数不限。因此$string1是匹配不成功的,$string2是匹配成功的。$string3是匹配成功的。

6. 模式修正符

我们通过元字符和原子完成了正则表达示的入门。有一些特殊情况我们依然需要来处理。
如果abc在第二行的开始处如何匹配?
我不希望正则表达示特别贪婪的匹配全部,只匹配一部份怎么办?
这个时候,我们就需要用到下面的这些模式匹配来增强正则的功能。

常用的模式匹配符有:
模式匹配符 功能
i 模式中的字符将同时匹配大小写字母.
m 字符串视为多行
s 将字符串视为单行,换行符作为普通字符.
x 将模式中的空白忽略.
A 强制仅从目标字符串的开头开始匹配.
D 模式中的美元元字符仅匹配目标字符串的结尾.
U 匹配最近的字符串.
模式匹配符的用法如下:/ 正则表达示/模式匹配符模式匹配符是放在正则表达式的最后的。
例如: /\w+/s

1. i 不区分大小写
<?php //在后面加上了一个i 
    $pattern = '/ABC/i'; 
$string = '8988abc12313';
$string1 = '11111ABC2222'; 
if(preg_match($pattern, $string, $matches)){
     echo '匹配到了,结果为:'; 
    var_dump($matches); }else{
     echo '没有匹配到';
     }
?>

结论,不论是$string还是$string1全都匹配成功了。因此,在后面加上了i之后,能够不共分匹配内容的大小写。

2. m 视为多行
正则在匹配的时候,要匹配的目标字符串我们通常视为一行。
“行起始”元字符(^)仅仅匹配字符串的起始,“行结束”元字符($)仅仅匹配字符串的结束。
当设定了此修正符,“行起始”和“行结束”除了匹配整个字符串开头和结束外,还分别匹配其中的换行符的之后和之前。
注意:如果要匹配的字符串中没有“\n”字符或者模式中没有 ^ 或 $,则设定此修正符没有任何效果。

我们通过实验和代码来验证一下这个特点:
第一次匹配,你会发现匹配不成功:(1)↓↓
<?php
$pattern = '/^a\d+/';
$string = "我的未来在自己手中我需要不断的努力
a9是一个不错的字符表示
怎么办呢,其实需要不断奋进";
if (preg_match($pattern, $string, $matches)) {
    echo '匹配到了,结果为:';
    var_dump($matches);
} else {
    echo '没有匹配到';
}
?>


第二次匹配,我们加上m 试试:(2)↓↓

<?php
$pattern = '/^a\d+/m';
$string = "我的未来在自己手中我需要不断的努力
a9是一个不错的字符表示
怎么办呢,其实需要不断奋进";
if (preg_match($pattern, $string, $matches)) {
    echo '匹配到了,结果为:';
    var_dump($matches);
} else {
    echo '没有匹配到';
}
?>

运行结果:
匹配到了,结果为:array(1) { [0]=> string(2) "a9" }

哦耶!匹配成功了。/^a\d+/ 匹配的内容是a9,必须得在行开始处。在第二行也被匹配成功了。

3. s 视为一行
如果设定了此修正符,模式中的圆点元字符(.)匹配所有的字符,包括换行符。

第一次,不加模式匹配符s:(1)↓↓
<?php

$pattern = '/新的未来.+\d+/';

$string = '新的未来
987654321';

if (preg_match($pattern, $string, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>


第二次,在正则表达示后面加上模式匹配符s:(2)↓↓

<?php

$pattern = '/新的未来.+\d+/s';

$string = "新的未来
987654321";

if (preg_match($pattern, $string, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

运行结果:
匹配到了,结果为:array(1) { [0]=> string(22) "新的未来 987654321" }

结论:

  1. 因为在新的未来,未来后面有一个换行
  2. 而.(点)是匹配非空白字符以外的所有字符。因此,第一次不成功
  3. 第二次,加上了s模式匹配符。因为,加上后.(点)能匹配所有字符。

4. x 忽略空白字符
1. 如果设定了此修正符,模式中的空白字符除了被转义的或在字符类中的以外完全被忽略。
2. 未转义的字符类外部的#字符和下一个换行符之间的字符也被忽略。
  • (1)↓↓我们先来实验一下忽略空白行等特性:
<?php

$pattern = '/a b c /x';

$string = '学英语要从abc开始';

if (preg_match($pattern, $string, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

运行结果:
匹配到了,结果为:array(1) { [0]=> string(3) "abc" }

这样也能匹配成功。
在$pattern里面有空格,每个abc后面有一个空格。而$string里面没有空格。
所以x忽略空白字符。

  • (2)↓↓而第二句话从字面上比较难理解:
<?php
//重点观察这一行
$pattern = '/a b c #我来写一个注释
/x';

$string = '学英语要从abc开始';

if (preg_match($pattern, $string, $matches)) {
   echo '匹配到了,结果为:';
   var_dump($matches);
} else {
   echo '没有匹配到';
}
?>

运行结果:
匹配到了,结果为:array(1) { [0]=> string(3) "abc" }

结果也匹配成功了!
我们发现,x的第二个特性是忽略:#字符和下一个换行符之间的字符也被忽略

5. e 将匹配项找出来,进行替换
e模式也叫逆向引用。主要的功能是将正则表达式括号里的内容取出来,放到替换项里面替换原字符串。
使用这个模式匹配符前必须要使用到preg_replace()
mixed preg_replace ( mixed $正则表达式 , mixed $用于取代字符串的字串 , mixed $目标字符串)
preg_replace的功能:使用正则表达式 ,找到目标字符串。然后用’用于取代字符串的字串’进行替换。

在正式讲解前我们回顾一下之前的知识,我们故意的把每个要匹配的原子外面都加上括号:↓↓

<?php
//加上了括号
$pattern = '/(\d+)([a-z]+)(\d+)/';

$string = '987abc321';

if (preg_match($pattern, $string, $match)) {
   echo '匹配到了,结果为:';
   var_dump($match);

} else {
   echo '没有匹配到';
}
?>

运行结果:
匹配到了,结果为:array(4) { [0]=> string(9) "987abc321" [1]=> string(3) "987" [2]=> string(3) "abc" [3]=> string(3) "321" }

这是我们之前讲括号的时候:匹配到的内容外面有括号。会把括号里面的内容,也放到数组的元素里面。如图中的:987、abc、321。


我们接下来看正则表达示中的e模式:↓↓

<?php
$string = "{April 15, 2003}";

//'w'匹配字母,数字和下划线,'d'匹配0-99数字,'+'元字符规定其前导字符必须在目标对象中连续出现一次或多次
$pattern = "/{(\w+) (\d+), (\d+)}/i";

$replacement = "\$2";

//字符串被替换为与第 n 个被捕获的括号内的子模式所匹配的文本
echo preg_replace($pattern, $replacement, $string);

?>

运行结果:
15

结论:

  1. 上例中\$2 指向的是正则表达示的第一个(\d+)。相当于把15又取出来了
  2. 替换的时候,我写上\$2。将匹配项取出来,用来再次替换匹配的结果。

6. U 贪婪模式控制
正则表达式默认是贪婪的,也就是尽可能的最大限度匹配。

我们来看看正则表达示是如何贪婪的:↓↓

<?php
$pattern = '/<div>.*<\/div>/';

$string = "<div>你好</div><div>我是</div>";

if (preg_match($pattern, $string, $match)) {
   echo '匹配到了,结果为:';
   var_dump($match);
} else {
   echo '没有匹配到';
}

运行结果:
匹配到了,结果为:array(1) { [0]=> string(34) "
你好
我是
" }
?>

我们来看看结果,得到如下结论。它从“
你好”直接匹配到了“我是
”。进行了最大范围的匹配。


同样一段代码我们再加大写的U,再看看效果:↓↓

<?php
$pattern = '/<div>.*<\/div>/U';

$string = "<div>你好</div><div>我是</div>";

if (preg_match($pattern, $string, $match)) {
   echo '匹配到了,结果为:';
   var_dump($match);
} else {
   echo '没有匹配到';
}

?>

运行结果:
匹配到了,结果为:array(1) { [0]=> string(17) "
你好
" }

我们发现,只匹配出来了:<div>你好</div>
这样,把正则的贪婪特性取消掉。让它找到了最近的匹配,就OK了。

7. A 从目标字符串的开头开始匹配
此模式类似于元字符中的^(抑扬符)效果。
<?php

$pattern = '/this/A';

$string = 'hello this is a ';
//$string1 = 'this is a ';

if (preg_match($pattern, $string, $match)) {
   echo '匹配到了,结果为:';
   var_dump($match);
} else {
   echo '没有匹配到';
}
?>

结论:
1.如果加A模式修正符的时候匹配不出来$string,不加时能匹配出来
2.如果加上了A模式修正符的时候能匹配出来$string1,因为必须要从开始处开始匹配

8. D 结束$符后不准有回车
如果设定了此修正符,模式中的美元元字符仅匹配目标字符串的结尾。没有此选项时,如果最后一个字符是换行符的话,美元符号也会匹配此字符之前。
<?php 
$pattern = '/\w+this$/'; 
$pattern1 = '/\w+this$/D'; 
$string = "hellothis "; 
if (preg_match($pattern1, $string, $match)) {
echo '匹配到了,结果为:'; 
var_dump($match);
}else {
echo '没有匹配到'; 
} 
?>

结论:
1.如pattern 在匹配$string的时候,$string的字符串this后有一个回车。在没有加D匹配符的时候也能匹配成功
2.如pattern 在匹配$string的时候,加上了D。$string的字符串this后有空格,匹配不成功。

7. 写正则的诀窍和常用正则

写正则的诀窍
女孩和男孩恋爱时的诀窍通常是:测试你是不是对我好一点,如果是的,咱们的关系就更好一点。
而正则的诀窍和恋爱的诀窍基本一致:写一点、测一点。
因为,我们需要不断的正则,用preg_match对比是不是能匹配成功。成功了,再写后面的一点。直到写完,全部匹配成功为止!
例如,我要写一个邮箱的正则。我先要做的事情,将常用的邮箱格式全部列出来。例如:
phpcn@php.cnphpcn@corp.baidu.cmphpcn@126.comphpcn@xxx.com12345@qq.com
常用的格式主要有这样一些。那我们就可以来分析:
1.先匹配@之前的字符 \w+(因为是0-9A-Za-z_)
2.第二个跟一个@符
3.第三个再写上[a-zA-Z0-9-]+ 因为qq和126这些主域名是不能有下划线的
4.corp.baidu. 或者是126. 通常邮箱后缀都是这样的。所以我们可以写成:([a-zA-Z0-9-]+.){1,2}
5.上面的是将 . 转义,让它是本身的意思。括号重复的区间最少一次,最多两次。
6.后面接下com|cn|org|gov.cn|net|edu.cn等就可以了

因此,我们的正则表达式我使用:
/\w+@([a-zA-Z0-9-]+.){1,2}(com|cn|org|gov.cn|net|edu.cn)/

/\w+@([a-zA-Z0-9_]+)\.(com|cn|org|gov.cn|net|edu.cn)/
邮箱的正则就被我写成功了。ฅʕ•̫͡•ʔฅ

8. 常用正则函数

函数名 功能
preg_filter 执行一个正则表达式搜索和替换
preg_grep 返回匹配模式的数组条目
preg_match 执行一个正则表达式匹配
preg_match_all 执行一个全局正则表达式匹配
preg_replace_callback_array 传入数组,执行一个正则表达式搜索和替换使用回调
preg_replace_callback 执行一个正则表达式搜索并且使用一个回调进行替换
preg_replace 执行一个正则表达式的搜索和替换
preg_split 通过一个正则表达式分隔字符串


正则关于面试常遇到的问题
面试中经常考到的几个正则达达示是:

  1. 匹配邮箱
  2. 匹配手机号
  3. 匹配一个网址
  4. 用正则匹配某个格式,取出某个例
  5. 写一个采集器
    其他….

面试的第4题和第5题我对大家不担心,因为只要大家认真学习了我给的前五节的内容。第4,5题推理就行。
因为,通常在技术答题面试环节,是时候准许查手机的! ヾ(๑╹◡╹)ノ”


  Reprint please specify: Treecatee PHP-正则表达式

 Previous
PHP-函数 PHP-函数
PHP函数分为自定义函数和系统函数 (o゚v゚)ノ    PHP 函数       一. 自定义函数1.1 自定义函数函数基本概念我们在实际开发过程当中需要有很多功能都需要反复
2019-02-15
Next 
PHP-命名空间 PHP-命名空间
(o゚v゚)ノ 如果没有定义任何命名空间,所有的类与函数的定义都是在全局空间,与 PHP 引入命名空间概念前一样。在名称前加上前缀 \ 表示该名称是全局空间中的名称,即使该名称位于其它的命名空间中时也是如此。对于函数和常量来说,如果当前
2019-02-14
  TOC