
本文详解如何使用 preg_match_all() 配合正确正则表达式,从字符串中精准提取所有形如 @@token@@ 的自定义令牌,并返回完整匹配数组,避免常见误区(如误用 preg_match 或错误字符类)。
本文详解如何使用 preg_match_all() 配合正确正则表达式,从字符串中精准提取所有形如 @@token@@ 的自定义令牌,并返回完整匹配数组,避免常见误区(如误用 preg_match 或错误字符类)。
在模板解析、内容占位符替换或配置化文本处理等场景中,常需识别并提取形如 @@address@@、@@street@@ 这类由双@符号包围的动态令牌。这类令牌名称通常由字母组成、长度不固定,且在原文中可能出现多次。若使用 preg_match(),仅能捕获首个匹配项,无法满足批量提取需求;而正则模式若写作 /@@[^a-z]@@/,则实际匹配的是“非字母字符”,与目标完全相反。
✅ 正确方案是:
- 使用 preg_match_all() 全局匹配所有符合模式的子串;
- 正则模式应为 /@@[a-z]+@@/:
- @@ 字面量匹配开头双@;
- [a-z]+ 匹配一个及以上小写字母(如需支持大写/数字/下划线,可扩展为 [a-zA-Z0-9_]+);
- 结尾 @@ 精确闭合。
以下是完整可运行示例:
<?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免费学习笔记(深入)”;
- 若令牌允许大小写字母、数字及下划线(如 @@userid@@),推荐使用更健壮的模式:/@@[a-zA-Z0-9]+@@/;
- 如需仅提取中间内容(去掉前后@@),可改用捕获组:/@@([a-zA-Z0-9_]+)@@/,此时结果位于 $matches[1];
- 注意:PHP 默认区分大小写,如需忽略大小写,可在模式末尾添加 i 修饰符,例如 /@@[a-z0-9_]+@@/i。
⚠️ 常见错误规避:
- ❌ preg_match() → 仅返回第一个匹配,无法满足多令牌提取;
- ❌ [^a-z] → 表示“非小写字母”,会匹配 @@123@@ 或 @@!@@,违背语义;
- ❌ 忘记量词 + → /@@[a-z]@@/ 只能匹配单字母令牌(如 @@a@@),无法匹配 @@name@@。
掌握该模式后,即可稳定、高效地支撑模板引擎、配置解析、动态文案生成等核心逻辑。











