如何从模板字符串提取数据?求更优雅的PHP实现方案
问题:通过模板从字符串中提取结构化数据
需求示例:
// 现有内容 $utterance = 'This is a brown bear with 7 kids'; $template = 'This is a {color} bear with {kids} kids'; // 期望输出 [ "color" => "brown", "kids" => "7", ]
当前使用的粗糙实现方案:
$regex = '/' . preg_replace('/{.*?}/' , '.*?', $template) . '/i'; foreach(preg_split('/\{.*?\}/', $template) as $part) { $utterance = str_replace($part, Str::startsWith($template, $part) || Str::endsWith($template, $part) ? '' : '|', $utterance); } preg_match_all('/{(.*?)}/', $template, $variables); $values = explode('|', $utterance); $variables = $variables[1]; array_combine($variables, $values);
希望得到更简洁的实现方式。
更简洁的实现方案
可以直接将模板转换为带捕获组的正则表达式,通过一次正则匹配就能提取对应变量的值,无需额外的字符串替换与拆分操作,代码逻辑更清晰高效:
// 提取模板中的变量名 preg_match_all('/\{(.*?)\}/', $template, $varMatches); $variableNames = $varMatches[1]; // 将模板转换为正则匹配模式:转义特殊字符,把{变量}替换为捕获组 $regexPattern = preg_replace('/\{.*?\}/', '(.*?)', preg_quote($template, '/')); $regexPattern = "/^$regexPattern$/i"; // 添加上下文边界确保完全匹配 // 执行匹配并提取结果 preg_match($regexPattern, $utterance, $valueMatches); array_shift($valueMatches); // 移除正则返回的完整匹配项 // 组合成目标键值对数组 $result = array_combine($variableNames, $valueMatches);
关键细节说明:
preg_quote($template, '/'):转义模板中的正则特殊字符(比如.,*等),避免破坏正则语法;- 捕获组规则:示例中用
(.*?)非贪婪匹配任意字符,若变量值仅为非空白字符,可改为([^\s]+?)提升匹配精度; - 边界约束:
^和$确保整个字符串与模板完全匹配,避免部分匹配导致的错误结果。
如果需要支持变量值包含空格的场景,上述代码直接可用;若变量值仅为数字或特定格式,可进一步调整捕获组的正则规则(比如数字用(\d+))。
内容的提问来源于stack exchange,提问作者Sebastian
相关产品推荐
相关产品推荐

