正则表达式是一种描述字符串排列的一种语法规则,通过该规则可以在一个大字符串中匹配出满足规则的子字符串。我们在程序的开发过程中,经常会遇到去对一类字符串进行处理的情况,比如在一堆字符串中查找是否含有邮箱,电话、手机号等。我们怎么描述匹配这些像邮箱、手机号等一类的字符串呢?这就要用到正则表达式。正则表达式不是PHP自己的东西,在JavaScript、Perl、Java等其他语言中也有可以使用。
PHP给我们提供了两套正则表达式处理函数。一种是由PCRE库提供的,与Perl语言兼容的正则表达函数;另一种是由POSIX扩展语法提供的正则表达式处理函数。两套正则处理功能类似,不过从PHP5.3以后,基于POSIX的已经被官方废除,因此我们一般使用基于PCRE库提供的正则处理函数。
1. 基于PCRE库的常用正则处理函数
文档:http://php.net/manual/zh/ref.pcre.php
preg_filter — 执行一个正则表达式搜索和替换
preg_grep — 返回匹配模式的数组条目
preg_last_error — 返回最后一个PCRE正则执行产生的错误代码
preg_match_all — 执行一个全局正则表达式匹配
preg_match — 执行一个正则表达式匹配
preg_quote — 转义正则表达式字符
preg_replace_callback — 执行一个正则表达式搜索并且使用一个回调进行替换
preg_replace — 执行一个正则表达式的搜索和替换
preg_split — 通过一个正则表达式分隔字符串
这些函数的具体使用方法我们可以查阅文档,后面我也会带着大家学习其中几个比较常用的函数。我们现在要记住的就是使用preg_match或者preg_match_all可以执行一个正则表达式匹配。
2. 正则表达式语法
前面我们说了,正则表达式可以理解为它就是一个匹配规则或者说是匹配模式,通过执行正则表达式,可以将符合规则的内容匹配出来。我们先直观的看一个简单的正则表达式:
我们想在一串字符串中匹配出QQ号:
preg_match('/^[0-9]{5,10}/','asdhsdjhjhvfdfg775678879sdhjkfdsjhgdf',$res);
2.1 定界符
如上面的例子,我们看到的’/[0-9]{5,10}/’就是一个正则表达式,我们看一下它的一个显著特点:被两个“/”包裹着内容。咱们称之为定界符。当然定界符不仅仅只能用“/”,也可以是其它的,比如“#”、“%”等,必过我们一般习惯使用“/”。
preg_match('#[0-9]{5,10}#','asdhsdjhjhvfdfg775678879sdhjkfdsjhgdf',$res);
3. 正则表达式的格式
基本格式:/原子和元字符/模式修正符
3.1 原子
3.1.1 原子分类
原子是正则表达式的最基本单位,每个模式至少要有一个原子,任何一种字符都可以作为原子,原子我们可以分为以下几类:
普通字符
我们常见的字符,如:大小写字母、数字等。
/f/ 用以匹配一段字符中是否含有“f”这个字符
/ff/ 用以匹配一段字符中是否含有“ff”这个字符串
特殊字符或者不可打印的字符
我们能打印出来的所有字符都可以作为原子,比如我们前面说的普通字符,同时呢,我们可以打印的还有很多需要转义使用的字符,比如“””、“’”、“/”等,这些字符作为原子的时候,需要使用转义字符“\”来取消他的特殊意义。
/\’/ 匹配一个字符串中是否含有“’”
/\
3.1.2 子模式(大原子)
后面详细讲解……
3.2 元字符
元字符不能单独存在,它被用来修饰原子。元字符根据其功能可以分为以下几类:
3.2.1 数量限定符
前面我们讲的原子都是一个原子匹配一次,有时候我们需要匹配多次的时候就可以用元字符里面的数量限定符来处理
限定符 | 含义 | 例子 |
---|---|---|
* | 匹配它前面原子0次或多次(贪婪匹配) | /ab*/,可以匹配a、ab、abbbbbb等 |
+ | 匹配它前面原子1次或多次(贪婪匹配) | |
? | 匹配它前面原子0次或1次 | |
{m} | 匹配它前面的原子m次 | |
{m,} | 匹配它前面原子m次或多次 | |
{m,n} | 匹配它前面原子最少m次,最多n次 |
3.2.2 边界限制符
边界限制符 | 含义 |
---|---|
^ | 从字符串开始位置匹配 |
$ | 匹配到字符串的尾部 |
\b | 描述字符串的前后边界 |
\B | 表示字符的非边界 |
3.2.3 模式选择符(|)
用“|”分割多个匹配模式,表示一个或者多个选项。
3.2.4 子模式符(“()”)
子模式也叫大原子,可以用“()”将多个原子包着组成一个独立单元
3.3 模式修正符
模式修正符是在正则表达式结尾定界符的外面使用。
修正符 | 意义 |
---|---|
i | 各模式进行匹配时不区分大小写 |
m | 将被匹配的字符串视为多行处理 |
s | 将被匹配的字符串视为单行处理 |
x | 忽略字符串中的空白,除非该空白被转义 |
u | 匹配模式里面的字符串会被当做utf-8的 |
…… | …… |
模式修正符表:http://php.net/manual/zh/reference.pcre.pattern.modifiers.php
3.4 子模式(大原子)
咱们前面讲的正则表达式一般是指一个匹配模式,多个匹配模式的话可以使用“|”分割。我们下面讲的子模式是指在一个模式中在进行分端处理。在一个匹配模式中使用“()”将一个或者多个原子包着组成一个独立单元,每个单元就叫一个子模式。
比如咱们匹配一段HTML代码:
$str = '<div>I am Div</div><span>I am Span</span>';
$pattern = '/<(div)>(.+)<\/(div)>/';
preg_match_all($pattern, $str, $res);
print_r($res);
通过例子,我们可以看到,每一个括号里面的东西都能被匹配到。正则表达式有一个比较厉害的功能就是:可以将子模式匹配成功的内容从左到右按顺序暂时存到缓冲区,可供以后使用。
存储子模式的缓冲区编号从1开始,连续编号至最大99个子表达式模式。每个缓冲区都可以使用“\n”(或用“$n”)访问,其中n为1至99的数字,用来按顺序标识特定缓冲区(子模式)。咱们看一个例子:
$str = '<div>I am Div</div><span>I am Span</span>';
$pattern = '/<(\w+)>(.+)<\/(\w+)>/';
//$pattern = '/<(\w+)>(.+)<\/(\1)>/';//双引号的时候使用\\1
preg_match_all($pattern, $str, $res);
print_r($res);
正则表达式功能十分强大,还有很多内容,对于刚入行的程序员,咱们先学到此。
4. PHP处理正则的常用函数
1. preg_match()
手册地址:http://php.net/manual/zh/function.preg-match.php
2. preg_match_all()
手册地址:http://php.net/manual/zh/function.preg-match-all.php
3. preg_grep (string pattern,array p a t t e r n , a r r a y input)
逐个将数组 input中的元素使用 i n p u t 中 的 元 素 使 用 pattern进行匹配,将匹配成功的值放到数组中返回
$arr = array('12345','qawdrt','22ddf','eeer443dd');
//$res = preg_grep('/\w+/',$arr);
//$res = preg_grep('/\d+/',$arr);
$res = preg_grep('/^\d+/',$arr);
//$res = preg_grep('/^\d+$/',$arr);
print_r($res);
4. preg_replace ( mixed pattern,mixed p a t t e r n , m i x e d replacement , mixed subject[,int s u b j e c t [ , i n t limit = -1 [, int &$count ]] )
搜索subject中匹配pattern的部分, 以replacement进行替换。
$subject = 'You are a dog, a dog that is disgusting';
$pattern = '/dog/';
$res = preg_replace($pattern, '***', $subject);
print_r($res);
subject为字符串, s u b j e c t 为 字 符 串 , pattern和 replacement为数组(如果 r e p l a c e m e n t 为 数 组 ( 如 果 replacement的数量比$pattern少,那么不足的部分将替换为空):
$subject = 'You are a dog, a dog that is disgusting. Sometimes you look like a pig. Sometimes you look like a donkey.';
$pattern = array('/dog/', '/pig/', '/donkey/');
$replace = array('***','+++','%%%');
$res = preg_replace($pattern, $replace, $subject);
print_r($res);
subject、 s u b j e c t 、 pattern、$replacement都为数组:
$subject = array(
'You are a dog, a dog that is disgusting. Sometimes you look like a pig. Sometimes you look like a donkey.',
'You stupid like a donkey'
);
$pattern = array('/dog/', '/pig/', '/donkey/');
$replace = array('***','+++','%%%');
$res = preg_replace($pattern, $replace, $subject);
print_r($res);
preg_split ( string pattern,string p a t t e r n , s t r i n g subject [, int limit=−1[,int l i m i t = − 1 [ , i n t flags = 0 ]] )
用符合正则表达式的字符分割字符串
$subject = 'english,chinese,japanese.french.german';
//$pattern = '/,/';
$pattern = '/[\.,]/';
$res = preg_split($pattern, $subject);
print_r($res);
匹配中文
$subject = '中国,I love you,你是我的骄傲';
preg_match_all('/[\x{4e00}-\x{9fa5}]+/u', $subject, $matches);
print_r($matches);