PHP 中的正则表达式

PHP 中的正则表达式(PCRE,Perl Compatible Regular Expressions)是处理字符串的强大工具,常用于验证格式 (如邮箱、手机号)、提取内容 (如从文本中抓链接)、替换字符 (如敏感词过滤)等。PHP 提供了专门的函数(如 preg_match()preg_replace())来执行正则操作,核心语法和通用正则一致,但有一些 PHP 特有的规则(如定界符、修饰符)。

一、PHP 正则的基础规则

在 PHP 中使用正则,必须遵守两个核心规则:

1. 定界符:包裹正则表达式

PHP 的正则必须用定界符 包裹(不能直接写纯正则),定界符可以是任意非字母数字的字符(常用 /#~)。

  • 示例:用 / 作为定界符 → /正则表达式/
  • 作用:区分正则本身和后续的修饰符(见下文),避免歧义。
2. 修饰符:调整匹配规则

修饰符放在定界符后面,用于改变正则的匹配行为(如是否区分大小写)。常用修饰符:

修饰符 作用 示例
i 不区分大小写匹配 /abc/i 会匹配 ABCaBc
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 位)

php 复制代码
$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。

示例:提取文本中所有邮箱

php 复制代码
$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"替换为" ")*

php 复制代码
$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 次或多次
php 复制代码
$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 次或多次
php 复制代码
$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 次
php 复制代码
$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. ():分组与捕获(提取子内容)
php 复制代码
$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. 验证邮箱格式(严格版)
php 复制代码
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">
php 复制代码
$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位用*代替)
php 复制代码
$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

五、注意事项

  1. 定界符冲突 :如果正则中包含定界符(如 /),需要转义(\/)或换其他定界符(如 #)。
    例:匹配 http:// 时,用 #http://#/http:\/\// 更简洁。
  2. 性能问题 :复杂正则(尤其是带 *+ 的贪婪匹配)在处理长字符串时可能卡顿,尽量优化正则(如用非贪婪 *?)。
  3. 转义字符 :PHP 字符串中的 \ 需转义为 \\,例如匹配 \d 时,正则应写为 /\\d/(因为 PHP 会先解析 \ 为转义)。

总结

PHP 正则的核心是:用定界符包裹正则 + 用专门函数执行操作 。掌握 preg_match()preg_match_all()preg_replace() 三个函数,结合元字符(*+?() 等)和修饰符,就能处理大多数字符串场景。多动手测试(比如修改上面的示例参数),很快就能熟练使用~

相关推荐
BingoGo2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack2 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo3 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack3 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack4 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端
BingoGo4 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
php
JaguarJack5 天前
告别 Laravel 缓慢的 Blade!Livewire Blaze 来了,为你的 Laravel 性能提速
后端·php·laravel
郑州光合科技余经理5 天前
代码展示:PHP搭建海外版外卖系统源码解析
java·开发语言·前端·后端·系统架构·uni-app·php
QQ5110082855 天前
python+springboot+django/flask的校园资料分享系统
spring boot·python·django·flask·node.js·php
WeiXin_DZbishe5 天前
基于django在线音乐数据采集的设计与实现-计算机毕设 附源码 22647
javascript·spring boot·mysql·django·node.js·php·html5