外观
正则表达式
约 875 字大约 3 分钟
2025-06-19
本文整理 PHP 中正则表达式的常用语法与匹配模式。
preg 函数速查
| 函数 | 说明 |
|---|---|
preg_match() | 匹配一次,返回匹配次数(0 或 1) |
preg_match_all() | 匹配所有,返回所有匹配结果 |
preg_replace() | 替换匹配的内容 |
preg_split() | 按正则分割字符串 |
preg_last_error() | 获取上次正则错误 |
基本语法
定界符
PHP 正则使用 / 作为定界符,也可以使用其他字符:
preg_match('/^abc$/', $str); // 常用 /
preg_match('#^abc#$', $str); // #
preg_match('!^abc!', $str); // !普通字符与元字符
| 类别 | 字符 | 说明 |
|---|---|---|
| 锚点 | ^ $ \b \B | 开头 / 结尾 / 单词边界 / 非单词边界 |
| 通配 | . [] [^] | 任意字符 / 字符集合 / 排除字符 |
| 量词 | * + ? {n} {n,} {n,m} | 0 或多个 / 1 或多个 / 0 或 1 / 精确 n 次 |
| 分组 | () (?:) (?=) (?! | 捕获组 / 非捕获组 / 正向先行 / 负向先行 |
| 选择 | | | 或 |
| 转义 | \\ | 反斜杠本身 |
| 预定义 | \d \w \s 及其大写 | 数字/单词字符/空白字符 |
量词默认贪婪,在后面加 ? 变为非贪婪:*? +? ?? {n,m}?
常用示例
匹配验证
// 手机号(中国大陆)
preg_match('/^1[3-9]\d{9}$/', $phone);
// 邮箱地址
preg_match('/^[\w.-]+@[\w.-]+\.\w+$/', $email);
// 身份证号(18 位)
preg_match('/^\d{17}[\dXx]$/', $idcard);
// URL
preg_match('/^https?:\/\/[^\s]+$/', $url);
// 汉字
preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $str);提取内容
// 从 HTML 中提取 title 标签内容
preg_match('/<title>(.*?)<\/title>/i', $html, $matches);
$title = $matches[1] ?? '';
// 从 URL 中提取参数
preg_match('/^\/users\/(\d+)/', '/users/123', $matches);
$userId = $matches[1]; // 123
// 匹配所有邮箱
preg_match_all('/[\w.-]+@[\w.-]+\.\w+/', $text, $matches);
$emailList = $matches[0];替换内容
// 去除多余空格
$str = preg_replace('/\s+/', ' ', $str);
// 手机号脱敏
$str = preg_replace('/(\d{3})\d{4}(\d{4})/', '$1****$2', $phone);
// 高亮关键词
$text = preg_replace('/(' . preg_quote($keyword, '/') . ')/i',
'<mark>$1</mark>', $text);分割字符串
// 按逗号/分号分割
$parts = preg_split('/[,;]+/', 'a,b;c,d');
// 按大写字母分割驼峰命名
$words = preg_split('/(?=[A-Z])/', 'userName');
// ['userName' -> 'user', 'Name']常用表达式汇总
数字与金额
| 需求 | 表达式 |
|---|---|
| 整数 | ^\d+$ |
| 正整数 | ^[1-9]\d*$ |
| 负整数 | ^- [1-9]\d*$ |
| 浮点数 | ^-?\d+(\.\d+)?$ |
| 两位小数金额 | ^[1-9]\d{0,}(,\d{3})*\.\d{1,2}$ |
字符串
| 需求 | 表达式 |
|---|---|
| 英文字母 | ^[a-zA-Z]+$ |
| 字母数字下划线 | ^\w+$ |
| 中文 | ^[\x{4e00}-\x{9fa5}]+$(需 u 修饰符) |
| 3-20 位字符 | ^.{3,20}$ |
日期与时间
| 需求 | 表达式 |
|---|---|
| 日期 YYYY-MM-DD | ^\d{4}-\d{1,2}-\d{1,2}$ |
| 时间 HH:mm:ss | ^\d{2}:\d{2}:\d{2}$ |
| 日期时间 | ^\d{4}-\d{1,2}-\d{1,2} \d{1,2}:\d{2}:\d{2}$ |
网络相关
| 需求 | 表达式 |
|---|---|
| IPv4 地址 | ^\d{1,3}(\.\d{1,3}){3}$ |
| 域名 | ^[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?$ |
| 邮政编码(中国) | ^[1-9]\d{5}$ |
注意事项
中文匹配需加
u修饰符(UTF-8):preg_match('/^[\x{4e00}-\x{9fa5}]+$/u', $str);特殊字符需要转义:
preg_quote('$40 for a g3/400', '/'); // \$40 for a g3\/400preg_match只匹配一次,需要全部匹配用preg_match_all:// 只匹配第一个 preg_match('/\d+/', 'abc123def456', $m); // ['123'] // 匹配全部 preg_match_all('/\d+/', 'abc123def456', $m); // ['123', '456']性能建议:正则表达式放在循环外编译,或使用
preg_quote处理动态内容。
