
本文介绍一种使用正则表达式精准分割混合文本与模板占位符(如 {{ attribute_a }})的方法,将其转化为统一格式的关联数组,区分纯文本段与可交互的下拉字段,适用于动态表单、模板引擎或低代码配置场景。
本文介绍一种使用正则表达式精准分割混合文本与模板占位符(如 `{{ attribute_a }}`)的方法,将其转化为统一格式的关联数组,区分纯文本段与可交互的下拉字段,适用于动态表单、模板引擎或低代码配置场景。
在构建可视化规则编辑器、模板渲染系统或配置驱动型表单时,常需将一段“半静态+半变量”的字符串(例如 "I am looking for {{ attribute_a }} with {{ attribute_b }}")解析为结构化数据,以便前端按类型分别渲染纯文本或下拉选择器。核心挑战在于:既要保留原始文本顺序,又要准确提取并标记所有 {{ ... }} 占位符及其内部名称。
推荐采用 preg_split() 配合 PREG_SPLIT_DELIM_CAPTURE 标志 的方案——它能在分割的同时完整保留分隔符本身,避免因多次正则匹配导致的边界错位或内容丢失。
以下是完整、健壮的 PHP 实现:
function tokenizeTemplateString(string $input): array
{
$result = [];
// 匹配 {{ 任意非 } 字符 }},支持空格和下划线等合法变量名
$pattern = '/(\{\{[^}]*\}\})/';
// 分割并捕获分隔符(即保留 {{...}} 作为独立数组元素)
$parts = preg_split($pattern, $input, -1, PREG_SPLIT_DELIM_CAPTURE);
foreach ($parts as $part) {
// 去除首尾空白(对文本和占位符均适用)
$trimmed = trim($part);
if ($trimmed === '') {
continue; // 忽略空片段(如开头/结尾空格或连续分隔符间空白)
}
// 判断是否为 {{...}} 形式(直接检查字符串起止即可,比 preg_match 更高效)
if (str_starts_with($trimmed, '{{') && str_ends_with($trimmed, '}}')) {
$name = trim(substr($trimmed, 2, -2)); // 安全移除 {{ 和 }}
$result[] = [
'type' => 'dropdown',
'name' => $name
];
} else {
$result[] = [
'type' => 'text',
'content' => $trimmed
];
}
}
return $result;
}
// 示例调用
$input = "I am looking for {{ attribute_a }} with {{ attribute_b }} to make {{ attribute_c }}";
$tokens = tokenizeTemplateString($input);
print_r($tokens);
✅ 关键优势说明:
-
不依赖嵌套正则匹配:原答案中在循环内重复调用
preg_match是冗余且低效的;本方案通过str_starts_with/str_ends_with直接判断结构,性能更优、逻辑更清晰; - 鲁棒性增强:显式跳过空片段,避免生成无意义的空文本项;
-
命名安全:
trim()确保变量名(如attribute_a)前后空格被清除,符合实际使用需求; -
可扩展性强:若后续需支持其他类型占位符(如
[[ ... ]]或{{{ ... }}}),只需调整正则和判断逻辑即可。
⚠️ 注意事项:
- 该正则
/(\{\{[^}]*\}\})/不支持嵌套大括号(如{{ outer {{ inner }} }}),但模板语法中应避免此类写法; - 若输入含未闭合的
{{,会导致匹配失败,建议在生产环境增加语法校验(如统计{{与}}数量); - 前端消费该数组时,应约定:
type === 'text'渲染为,type === 'dropdown'渲染为并绑定name字段。
此方法简洁、可靠,是处理类 Mustache/Handlebars 模板片段结构化解析的标准实践。











