Skip to content

正则表达式实用技巧

正则表达式是强大的文本处理工具。本文介绍 PHP 中常用的正则表达式场景。

基础匹配函数

php
// preg_match - 匹配一次
if (preg_match('/php/i', 'I love PHP')) {
    echo '匹配成功';
}

// preg_match_all - 匹配所有
preg_match_all('/\d+/', '订单 123, 456, 789', $matches);
print_r($matches[0]);  // ['123', '456', '789']

// preg_replace - 替换
$text = preg_replace('/\s+/', ' ', 'Hello    World');  // 'Hello World'

// preg_split - 分割
$parts = preg_split('/[,;]/', 'a,b;c');  // ['a', 'b', 'c']

常用验证模式

php
// 手机号验证(中国大陆)
function isMobile($mobile) {
    return preg_match('/^1[3-9]\d{9}$/', $mobile);
}

// 邮箱验证
function isEmail($email) {
    return preg_match('/^[\w\-.]+@[\w\-.]+\.\w+$/', $email);
}

// 身份证号(18位)
function isIdCard($id) {
    return preg_match('/^\d{17}[\dXx]$/', $id);
}

// URL 验证
function isUrl($url) {
    return preg_match('/^https?:\/\/.+/', $url);
}

// 中文字符
function hasChinese($str) {
    return preg_match('/[\x{4e00}-\x{9fa5}]/u', $str);
}

// 密码强度(8-20位,包含字母和数字)
function isStrongPassword($pwd) {
    return preg_match('/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d@$!%*?&]{8,20}$/', $pwd);
}

数据提取

php
$text = '
    联系人:张三,电话:13800138000
    联系人:李四,电话:13900139000
';

// 提取所有手机号
preg_match_all('/1[3-9]\d{9}/', $text, $phones);

// 提取姓名和电话
preg_match_all('/联系人:(\S+),电话:(\d{11})/', $text, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
    echo "姓名: {$match[1]}, 电话: {$match[2]}\n";
}

// 命名捕获组(PHP 7.3+)
preg_match_all('/联系人:(?<name>\S+),电话:(?<phone>\d{11})/', $text, $matches);
foreach ($matches['name'] as $i => $name) {
    echo "$name: {$matches['phone'][$i]}\n";
}

替换技巧

php
// 手机号脱敏
$mobile = '13800138000';
$masked = preg_replace('/(\d{3})\d{4}(\d{4})/', '$1****$2', $mobile);
// 138****8000

// 格式化金额
$price = 1234567.89;
$formatted = preg_replace('/\B(?=(\d{3})+(?!\d))/', ',', $price);
// 1,234,567.89

// 过滤危险标签(简单示例,生产环境用 HTML Purifier)
$html = '<script>alert("xss")</script><p>正文</p>';
$safe = preg_replace('/<script[^>]*>.*?<\/script>/is', '', $html);

// 替换多个空格为单个
$text = preg_replace('/\s+/', ' ', $text);

// 换行符统一
$text = preg_replace('/\r\n|\r/', "\n", $text);

修饰符说明

php
// i - 不区分大小写
preg_match('/php/i', 'PHP');  // 匹配

// u - UTF-8 模式(处理中文必需)
preg_match('/^\x{4e00}+$/u', '中文');  // 匹配

// s - 点号匹配换行
preg_match('/hello.world/s', "hello\nworld");  // 匹配

// m - 多行模式
preg_match_all('/^\d+/m', "1\n2\n3", $m);  // 匹配每行开头数字

// 组合使用
preg_match('/中文+/ius', "中文中文\n中文");

注意事项

  1. 优先使用字符串函数:简单的替换用 str_replace 更快
  2. 转义特殊字符:preg_quote() 转义正则特殊字符
  3. 避免贪婪匹配:大文本处理使用非贪婪量词 .*?
  4. 性能考虑:复杂正则可能很慢,考虑分步处理
php
// 转义特殊字符
$keyword = 'C++';
$safe = preg_quote($keyword, '/');  // C\+\+
$pattern = "/$safe/i";

Binstork