
本文详解如何使用 preg_match_all() 配合正确正则模式,精准提取字符串中所有形如 @@token@@ 的标识符,并返回为数组;重点纠正常见误区(如误用 preg_match、错误字符类 [^a-z])。
本文详解如何使用 preg_match_all() 配合正确正则模式,精准提取字符串中所有形如 @@token@@ 的标识符,并返回为数组;重点纠正常见误区(如误用 preg_match、错误字符类 [^a-z])。
在 PHP 开发中,常需从模板字符串中动态提取占位符(例如 @@username@@、@@email@@),这类标记通常以双 @ 符号包裹纯字母标识符。若使用 preg_match(),仅能捕获首个匹配项,无法满足批量提取需求;而正则模式 /@@[^a-z]@@/ 存在两个关键缺陷:
- [^a-z] 表示“非小写字母”,会匹配空格、符号甚至换行符,导致匹配失败或误匹配;
- 缺少量词(如 +),无法匹配多字符 token(如 address 有 7 个字母,单个 [a-z] 只能匹配首字母)。
✅ 正确做法是:
- 使用 preg_match_all() —— 专为全局匹配设计,返回全部匹配结果;
- 采用正则模式 /@@[a-z]+@@/:
- @@ 字面量匹配起始双 @;
- [a-z]+ 匹配一个及以上连续小写字母(若需支持大写/数字/下划线,可扩展为 [a-zA-Z0-9_]+);
- @@ 字面量匹配结尾双 @;
- 结果存储在 $matches[0] 中(完整匹配项数组),无需手动索引。
以下为完整可运行示例:
<?php
$input = 'my address is @@address@@ and my house is at @@street@@ and the number is @@number@@ or so';
// ✅ 正确:全局匹配所有 @@xxx@@ 格式
preg_match_all('/@@[a-z]+@@/', $input, $matches);
// $matches[0] 是包含所有完整匹配字符串的一维数组
$output = $matches[0];
var_dump($output);
// 输出:
// array(3) {
// [0]=> string(11) "@@address@@"
// [1]=> string(10) "@@street@@"
// [2]=> string(10) "@@number@@"
// }
?>⚠️ 注意事项:
立即学习“PHP免费学习笔记(深入)”;
- 若 token 可能含大写字母(如 @@UserName@@)、数字(@@user123@@)或下划线(@@first_name@@),请将模式升级为 /@@[a-zA-Z0-9_]+@@/;
- 如需提取 @@ 内部内容(即 address 而非 @@address@@),可使用捕获组:/@@([a-zA-Z0-9_]+)@@/,此时 $matches[1] 即为目标 token 数组;
- 模式未启用 i 修饰符时区分大小写;添加 i(如 /@@[a-z0-9_]+@@/i)可统一忽略大小写;
- 避免使用 .* 等贪婪匹配,防止跨 token 错误合并(如 @@a@@ and @@b@@ 被误匹配为 @@a@@ and @@b@@ 整体)。
总结:提取 @@...@@ 类型 token 的核心是「全局匹配 + 精确字符集 + 合理量词」。牢记 preg_match_all() 替代 preg_match,并严格校验正则逻辑,即可稳健实现模板解析、动态替换等常见业务场景。











