
本文详解如何使用 preg_match_all() 配合正确正则表达式,从字符串中精准提取所有形如 @@token@@ 的标识符,并返回为数组,避免常见匹配失败、遗漏或多匹配错误。
本文详解如何使用 preg_match_all() 配合正确正则表达式,从字符串中精准提取所有形如 @@token@@ 的标识符,并返回为数组,避免常见匹配失败、遗漏或多匹配错误。
在 PHP 开发中,常需从模板字符串(如邮件正文、配置文本或前端占位符)中提取自定义标记,典型格式为双 @ 符号包裹的标识符,例如 @@username@@、@@order_id@@ 或 @@created_at@@。这类需求看似简单,但若正则设计不当,极易导致匹配失败、空结果或误匹配。
✅ 正确做法:使用 preg_match_all() + 精准模式
preg_match() 仅返回首个匹配项,而提取全部 token 必须使用 preg_match_all()。同时,原始正则 /@@[^a-z]@@/ 存在两个关键错误:
- [^a-z] 表示「非小写字母」,会匹配空格、@、数字甚至换行符,完全违背意图;
- 缺少量词(如 + 或 *),导致只能匹配单个字符,无法捕获 address 这类多字母 token。
✅ 推荐正则模式:
/@@[a-z]+@@/
- [a-z]+:匹配一个及以上小写字母(若需支持大写、数字或下划线,可扩展为 [a-zA-Z0-9_]+);
- @@:字面量匹配起始与结束分隔符;
- 整体确保只捕获合法 token,不越界、不截断。
? 完整可运行示例
<?php
$input = 'my address is @@address@@ and my house is at @@street@@ and the number is @@number@@ or so';
// 使用 preg_match_all 提取全部匹配项
preg_match_all('/@@[a-z]+@@/', $input, $matches);
// $matches[0] 是完整匹配结果数组(即所有 @@xxx@@)
$output = $matches[0];
print_r($output);
// 输出:
// Array
// (
// [0] => @@address@@
// [1] => @@street@@
// [2] => @@number@@
// )
?>⚠️ 注意事项与进阶建议
- 大小写兼容:若 token 可能含大写字母(如 @@UserName@@),请改用 /@@[a-zA-Z]+@@/;
- 支持数字与下划线(推荐用于变量名):/@@[a-zA-Z0-9_]+@@/;
- 避免贪婪匹配陷阱:当前模式已足够安全,无需 ? 非贪婪修饰——因为 @@ 是明确边界;
- 空 token 防御:若存在 @@@@ 这类非法情况,上述正则自动忽略(因 [a-z]+ 要求至少一个字母);
- 性能提示:对超长文本,建议添加 PREG_OFFSET_CAPTURE 标志定位位置,或预判输入长度做合理性校验。
✅ 总结
提取 @@xxx@@ 类 token 的核心是:用 preg_match_all() 替代 preg_match(),并采用语义明确的字符类(如 [a-z]+)替代否定类 [^a-z]。一次写对正则,即可稳定、高效、可维护地完成模板解析任务。
立即学习“PHP免费学习笔记(深入)”;











