世界上最难懂的是道士的鬼符、医生的处方和程序员的正则表达示。(ง •_•)ง
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 '没有匹配到';
}
?>
(2)↓↓因为我希望的是匹配a,而$string当是是不存在a的,所以不成功。
<?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] |
[ ] | 指定范围的原子 |
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 '没有匹配到';
}
?>
结论:
- 匹配$string不成功,但是匹配$string1的时候成功。因为中括号里面有个抑扬符。
- ^ 抑扬符在中括号里面的作用是不准以中括号里面的字符进行匹配。
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" }
结论:
- 因为在新的未来,未来后面有一个换行
- 而.(点)是匹配非空白字符以外的所有字符。因此,第一次不成功
- 第二次,加上了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
结论:
- 上例中\$2 指向的是正则表达示的第一个(\d+)。相当于把15又取出来了
- 替换的时候,我写上\$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.cn phpcn@corp.baidu.cm phpcn@126.com phpcn@xxx.com 12345@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 | 通过一个正则表达式分隔字符串 |
正则关于面试常遇到的问题
面试中经常考到的几个正则达达示是:
- 匹配邮箱
- 匹配手机号
- 匹配一个网址
- 用正则匹配某个格式,取出某个例
- 写一个采集器
其他….
面试的第4题和第5题我对大家不担心,因为只要大家认真学习了我给的前五节的内容。第4,5题推理就行。
因为,通常在技术答题面试环节,是时候准许查手机的! ヾ(๑╹◡╹)ノ”