PHP 中的正则表达式
PHP 中的正则表达式(PCRE,Perl Compatible Regular Expressions)是处理字符串的强大工具,常用于验证格式(如邮箱、手机号)、提取内容(如从文本中抓链接)、替换字符(如敏感词过滤)等。PHP 提供了专门的函数(如 preg_match()
、preg_replace()
)来执行正则操作,核心语法和通用正则一致,但有一些 PHP 特有的规则(如定界符、修饰符)。
一、PHP 正则的基础规则
在 PHP 中使用正则,必须遵守两个核心规则:
1. 定界符:包裹正则表达式
PHP 的正则必须用定界符包裹(不能直接写纯正则),定界符可以是任意非字母数字的字符(常用 /
、#
、~
)。
- 示例:用
/
作为定界符 →/正则表达式/
- 作用:区分正则本身和后续的修饰符(见下文),避免歧义。
2. 修饰符:调整匹配规则
修饰符放在定界符后面,用于改变正则的匹配行为(如是否区分大小写)。常用修饰符:
修饰符 | 作用 | 示例 |
---|---|---|
i | 不区分大小写匹配 | /abc/i 会匹配 ABC 、aBc 等 |
g | 全局匹配(默认只匹配一次,用 preg_match_all() 配合) | /a/g 会匹配所有 a |
m | 多行模式(^ 匹配每行开头,$ 匹配每行结尾) | /^hello/m 匹配多行文本中每行的 hello 开头 |
s | 单行模式(. 匹配换行符 \n ) | /a.b/s 可匹配 a\nb (默认 . 不匹配 \n ) |
二、PHP 正则核心函数
PHP 提供了多个正则处理函数,最常用的有以下 3 个:
1. preg_match()
:检查是否匹配(只匹配一次)
- 语法:
preg_match(正则, 目标字符串, 匹配结果数组)
- 作用:判断目标字符串是否符合正则模式,只返回第一个匹配结果。
- 返回值:匹配成功返回
1
,失败返回0
,错误返回false
。
示例:验证手机号(中国大陆 11 位)
$phone = "13800138000";
// 正则:以1开头,第二位3-9,后面9位数字(用/作为定界符)
$pattern = '/^1[3-9]\d{9}$/';// 执行匹配,结果存到$matches数组
if (preg_match($pattern, $phone, $matches)) {echo "手机号格式正确!匹配到:" . $matches[0]; // 输出:手机号格式正确!匹配到:13800138000
} else {echo "格式错误";
}
$matches[0]
是完整匹配的结果;如果正则有分组(()
),$matches[1]
、$matches[2]
等是分组内容。
2. preg_match_all()
:全局匹配(获取所有匹配结果)
- 语法:
preg_match_all(正则, 目标字符串, 匹配结果数组)
- 作用:找到目标字符串中所有符合正则的内容,结果存到二维数组中。
- 返回值:返回完整匹配次数(可能是0),或者如果发生错误返回FALSE。
示例:提取文本中所有邮箱
$text = "我的邮箱是a@test.com,你的是b_123@example.cn,还有c+abc@mail.com";
// 正则:匹配邮箱(简化版,用#作为定界符,避免/转义)
$pattern = '#\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*#';// 全局匹配所有邮箱
preg_match_all($pattern, $text, $matches);// $matches[0] 是所有匹配的邮箱数组
print_r($matches[0]);
// 输出:
// Array (
// [0] => a@test.com
// [1] => b_123@example.cn
// [2] => c+abc@mail.com
// )
3. preg_replace()
:替换匹配的内容
- 语法:
preg_replace(正则, 替换内容, 目标字符串)
- 作用:找到所有符合正则的内容,替换为指定字符串。
示例:过滤敏感词(将“bad”替换为“”)*
$text = "This is a bad word, bad idea!";
$pattern = '/bad/i'; // i修饰符:不区分大小写(匹配bad、Bad、BAD等)
$replacement = '***';// 替换所有匹配的内容
$result = preg_replace($pattern, $replacement, $text);
echo $result; // 输出:This is a ***word,*** idea!
三、核心元字符与 PHP 示例
结合 PHP 函数,再巩固下常用元字符的用法(重点理解 *
、+
、?
、()
等):
1. *
:匹配前面的字符 0 次或多次
$str = "ac, abc, abbc";
$pattern = '/ab*c/'; // b可以出现0次、1次、多次preg_match_all($pattern, $str, $matches);
print_r($matches[0]); // 输出:Array ( [0] => ac [1] => abc [2] => abbc )
2. +
:匹配前面的字符 1 次或多次
$str = "ac, abc, abbc";
$pattern = '/ab+c/'; // b至少出现1次preg_match_all($pattern, $str, $matches);
print_r($matches[0]); // 输出:Array ( [0] => abc [1] => abbc )(不匹配ac,因为b出现0次)
3. ?
:匹配前面的字符 0 次或 1 次
$str = "color, colour";
$pattern = '/colou?r/'; // u可以出现0次或1次(匹配color或colour)preg_match_all($pattern, $str, $matches);
print_r($matches[0]); // 输出:Array ( [0] => color [1] => colour )
4. ()
:分组与捕获(提取子内容)
$url = "https://www.example.com/path?query";
// 正则:匹配://,然后用()捕获域名(非/的字符)
$pattern = '/:\/\/([^/]+)/'; // ()是分组,用于提取域名preg_match($pattern, $url, $matches);
echo $matches[0]; // 输出:://www.example.com(完整匹配)
echo $matches[1]; // 输出:www.example.com(第一个分组的内容,即我们要的域名)
四、实战案例:常见场景处理
1. 验证邮箱格式(严格版)
function isEmail($email) {// 正则:支持字母、数字、下划线、+-., 域名支持多级(如.co.uk)$pattern = '/^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/';return preg_match($pattern, $email) === 1;
}var_dump(isEmail("test@example.com")); // bool(true)
var_dump(isEmail("test+abc@mail.co.uk")); // bool(true)
var_dump(isEmail("test@.com")); // bool(false)(域名不合法)
2. 从 HTML 中提取所有图片链接(<img src="xxx">
)
$html = '<img src="pic1.jpg"><img src="images/pic2.png">';
// 正则:匹配<img src="...",捕获引号中的链接(用~作为定界符,避免/转义)
$pattern = '~<img src="([^"]+)"~';preg_match_all($pattern, $html, $matches);
print_r($matches[1]); // 输出:Array ( [0] => pic1.jpg [1] => images/pic2.png )
3. 格式化手机号(中间4位用*代替)
$phone = "13800138000";
$pattern = '/(\d{3})(\d{4})(\d{4})/'; // 分3组:前3位、中间4位、后4位
$replacement = '$1****$3'; // $1引用第一组,$3引用第三组echo preg_replace($pattern, $replacement, $phone); // 输出:138****8000
五、注意事项
- 定界符冲突:如果正则中包含定界符(如
/
),需要转义(\/
)或换其他定界符(如#
)。
例:匹配http://
时,用#http://#
比/http:\/\//
更简洁。 - 性能问题:复杂正则(尤其是带
*
、+
的贪婪匹配)在处理长字符串时可能卡顿,尽量优化正则(如用非贪婪*?
)。 - 转义字符:PHP 字符串中的
\
需转义为\\
,例如匹配\d
时,正则应写为/\\d/
(因为 PHP 会先解析\
为转义)。
总结
PHP 正则的核心是:用定界符包裹正则 + 用专门函数执行操作。掌握 preg_match()
、preg_match_all()
、preg_replace()
三个函数,结合元字符(*
、+
、?
、()
等)和修饰符,就能处理大多数字符串场景。多动手测试(比如修改上面的示例参数),很快就能熟练使用~