作者的话
正则表达式的定义可以这样简单概括:“正则表达式描述了一种字符串匹配的模式,通过这个模式在特定的函数中对字符串进行匹配、查找、替换及分割等操作。作为一个匹配模板,是由原子、特有功能字符及模式修正符三部分组成的文字模式。”这里是我总结PHP正则表达式的定义及简单使用。
术语概念
- 元字符:具有特殊含义的字符,如^(开始)和$(结束);
- 原子:用来匹配的字符,如果 \d(匹配0到9);
定界符
除了字母、数字和反斜线‘\’以外的任何字符都可以作为定界符,如 #、!等都是可以作为定界符,但是行业习惯这样做:/正则表达式/。
元字符
元字符 | 含义 |
---|---|
* | 0次1次或多次 |
+ | 1次或多次 |
? | 0次或1次 |
. | 除了除了换行外的其他字符 |
| | 或选择 |
{n} | 正好n次 |
{n,} | 不少于n次 |
{n,m} | 区间,>=n,<=m |
^或\A | 正则的开始 |
$或\Z | 正则的结束 |
\b | 单词的边界 |
\B | 单词边界以外 |
[] | 其中任意一个 |
[^] | 除了[]中的以外 |
() | 作为一个整体 |
原子
一些特殊符号,如:* ’ ” + \等,需要使用 \ 来进行转义。
原子字符 | 含义 | 举例 |
---|---|---|
\cx | 匹配由x指明的控制字符 | 如 \cM匹配一个回车符,x的值必须为A~Z或a~z之一,否则将c视为匹配‘c’ |
\f | 匹配一个换页符 | |
\n | 匹配一个换行符 | |
\r | 匹配一个回车符 | |
\t | 匹配一个指标符 | 在不使用表格的情况下在垂直方向按列对齐文本 |
\v | 匹配一个垂直制表符 | |
\d | 0到9任意一个数字 | 等价于[0-9] |
\D | 除0到9之外的字符 | 等价于[^0-9] |
\s | 空白字符 | 等价于[\f\n\r\t\v] |
\S | 除了空白字符 | |
\w | 数字、字母或下划线 | [0-9a-zA-Z] |
\W | 除了数字、字符或下划线 | 可以理解为特殊字符,如*、$等 |
示例:匹配139开头的手机号码
$str = '13912345678';
$pattern = '/^139\d{8}$/';
$res_int = preg_match($pattern, $str, $matches);
if ($res_int) {
var_dump($matches);
} else {
var_dump('无法匹配');
}
模式修正符
在最后一个细线‘/’之后使用,如 /php/i
模式修正符 | 含义 |
---|---|
i | 不区分大小写 |
m | 将字符视为多行 |
s | 将字符串视为单行,换行符作为普通的字符 |
x | 忽略空白 |
U | 取消贪婪模式,等同于在数量符之后添加一个问号,比如 .*? |
后向引用
使用()时,会将其相关的匹配存储到一个临时的缓存区,缓存区编号从1-99,使用 \1(“\1”)来获取缓存区内容,可以使用 ?: 或 ?= 或 ?! 来忽略相关的缓存内容。
/(windows)(linxu)\2/ 这样是使用第二个缓存区的内容,linux;
/(?:windows)(linux)\1/,忽略了第一缓存区的内容,linux。
贪婪模式
概念不好解释,直接上代码去理解
$str = '发财123发财发财456发财发财abc发财';
$pattern = '/发财.*发财/'; // 匹配始末发财中的内容
$pattern2 = '/发财.*?发财/'; // 匹配所有发财中的内容
$pattern3 = '/发财.*发财/U'; // 效果等同上一行
preg_match_all($pattern, $str, $matches);
preg_match_all($pattern2, $str, $matches2);
preg_match_all($pattern3, $str, $matches3);
var_dump($matches);
var_dump($matches2);
var_dump($matches3);
结果是这样的
中文匹配
这个不常用到,知道要点即可。
- UTF-8汉字编码范围是:0x4e00–0x9fa5,使用 u 模式修正符使字符串被当成UTF-8。
- gb2312汉字编码范围是:0xb0–0xf7,0xa1–0xfe,使用 chr 将其转为字符串。
常用函数
preg_match
preg_match_all
preg_match返回0或者1,它在完成第一次匹配后停止搜索;preg_match_all会一直匹配目标到结束;如果如果发生错误preg_match()返回 FALSE。
preg_replace
preg_split
使用命名子组
有多个匹配条件,获取其中的某个条件下的匹配结果。
$str = 'foobar: 2008';
preg_match('/(?P<name>\w+): (?P<digit>\d+)/', $str, $matches);
/* 下面例子在php 5.2.2(pcre 7.0)或更新版本下工作, 然而, 为了后向兼容, 上面的方式是推荐写法. */
// preg_match('/(?<name>\w+): (?<digit>\d+)/', $str, $matches);
var_dump($matches);
输出结果:
或者不使用 ?P name 这样的语法:
$str = 'foobar: 2008';
preg_match('/(\w+): (\d+)/', $str, $matches2);
// 这样会把结果直接保存到内容中
var_dump($matches2);
输出结果: