kano个人博客讲解php之正则表达式

kano个人技术博客 php教程 1,193 次浏览 没有评论

本篇的标题其实有点儿名不副实,说是php”的正则表达式,但实际上因为正则自有一套语法,在各个语言中的实现其实差不很多,所以“php”这个限定词其实并不是那么的重要,更主要的是一篇正则的介绍。

“搜索”这个需求即使不是程序员也会经常的用到,而程序员更是家常便饭,但是有时候搜索的东西可能不是那么的明确:比如想搜索一个手机号码,但是记不清手机号码的后几位;想搜索文章中的一个英文单词,但根本想不起来这个英文单词是什么;想在源码中搜索一张以“cy”开头的jpg图片……

正则表达式

如此种种需求,用普通的字符串搜索是根本做不到的,这时候就需要正则表达式了,正则表达式是一种对字符串的“模式匹配”,而不是简单的字符匹配,比如上面说的搜索手机号码,实际上是想“查找一个连续的11个数字”,或者更具体的需求,比如131或156开头的号码,那就是“131或156开头,后面连续8个数字”。诸如此类的描述,都可以用正则表达式简单的表达出来。

下面我们来逐一讲解正则中的概念。

一、概念介绍

正则中的一些字符被赋予了特殊的意义,使它们可以代表某种模式而不是单纯的字符,这些字符称为元字符:{

\  转义字符,某些字符前面加上\就变成了元字符,如“\d”;有些时候我们则会想匹配元字符本身的字符也会用\转义,如“\^”

.  匹配除了换行符外的任何一个字符

|  或运算符,如“cat|dog”匹配单词“cat”或“dog”

 

// 匹配数量

?  0次或1次匹配

+  匹配一次或多次

*  匹配0次或多次

{m}  匹配m次

{m,n}  匹配m~n次,包括m和n

{m,}  至少匹配m次

※ “?+*”这三个元字符都可以用{m,n}来表示:?等价于{0,1},+等价于{1,},*等价于{0,}

 

// 匹配位置

^  匹配行开头

$  匹配行结尾

\b  匹配单词边界

 

// 字符类

\s  匹配空白字符

\S  匹配非空白字符

\w  匹配单词字符(具体来说等价于[0-9a-zA-Z_],数字字母下划线,和标识符的命名规则比较像,还是比较好记的)

\W  匹配非单词字符

\d  匹配数字

\D  匹配非数字

※ 上面的小写大写字母成对出现的元字符匹配的范围是互斥的

 

// 字符组

[…]  匹配[]中任意一个字符(注意是“一个”)

[^…]  匹配除了…外的任意一个字符

}

二、例子

常用的元字符介绍完了,估计没用过正则的小伙伴们还是一脸懵逼,下面我们来实际操练一下,就会发现正则其实很简单。

例子1

我们从前面举的例子,匹配一个电话号码开始吧,匹配一个131开头的号码:

echo preg_match('/131\d{8}/', '13158746521') ? '匹配' : '不匹配';  // 匹配

是匹配的,但是等等,如果是一个很长的数字,其中包含131呢:

echo preg_match('/131\d{8}/', '2342313158746521484848') ? '匹配' : '不匹配';  // 匹配

我们发现这个也是匹配的!因为我们只限定了131后面紧跟着8个数字这么一个条件,前后无论是什么都会匹配,这显然不是我们想要的,我们想要的其实是这一串字符的前后要么没有其他字符了,如果有字符的话则希望其不是数字,所以下面这个才是我们需要的:

echo preg_match('/([^\d]|\b)131\d{8}([^\d]|\b)/', '13158746521') ? '匹配' : '不匹配';  // 匹配
echo preg_match('/([^\d]|\b)131\d{8}([^\d]|\b)/', '13158746521aa') ? '匹配' : '不匹配';  // 匹配
echo preg_match('/([^\d]|\b)131\d{8}([^\d]|\b)/', '6313158746521aa') ? '匹配' : '不匹配';  // 不匹配

看起来有些复杂,kano稍微解释一下:

\d匹配的是任意一个数字,[^\d]则匹配任意一个非数字(当然也可以用\D),\b表示单词边界,所以([^\d]|\b)表示匹配单词边界或者一个非数字。

例子2

匹配一个日期:

echo preg_match('/^\d{4}-\d{1,2}-\d{1,2}/', '2018-12-31') ? '匹配' : '不匹配';  // 匹配
echo preg_match('/^\d{4}-\d{1,2}-\d{1,2}/', '2018-5-18') ? '匹配' : '不匹配';  // 匹配

由于月和日有可能有前置0也可能没有前置0,所以用了数量限定{1,2},有时候日期还会用/作为分隔符,比如“2018/05/18”,我们可以用下面的正则:

echo preg_match('/^\d{4}[-\/]\d{1,2}[-\/]\d{1,2}/', '2018/05/18') ? '匹配' : '不匹配';  // 匹配

注意其中的“/”用了反斜杠转义,因为“/”在这里是php正则的分隔符,正则都写在了“//”之中,所以是有特殊含义的字符,必须转义。

到这里,大家是不是对php的正则有了一定的了解,觉得其实很简单?实际正则就是一个第一眼看了眼花,但是很快能上手的东西。正则在编程中是必不可少的东西,请大家务必多多练习,熟练掌握。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Go