str_replace批量替换{{key}}占位符时,顺序和数组结构关键,因按数组顺序逐个替换,短占位符(如{{user}})若先于长占位符(如{{user_name}})会导致后者被截断无法匹配;正确做法是按长度倒序排列搜索数组或改用无包含关系的命名规范。

PHP 用 str_replace 批量替换 {{key}} 占位符时,为什么顺序和数组结构很关键
直接传两个平行数组给 str_replace 看似简单,但若占位符之间存在嵌套或前缀关系(比如 {{user}} 和 {{user_name}}),先替换短的会导致长的被提前截断。例如把 {{user}} 换成 "Alice" 后,{{user_name}} 就变成 "Alice_name",再也匹配不上。
正确做法是:按占位符长度倒序排列,或拆成单次调用避免干扰。更稳妥的是用关联数组 + str_replace 的多参数形式:
- 构造
$search数组时,确保所有占位符不互相包含;可加前缀/后缀(如[[user]])或统一用双大括号且命名无歧义 - 使用
str_replace(array_keys($replacements), array_values($replacements), $html),其中$replacements是['{{username}}' => '张三', '{{email}}' => 'zhang@example.com'] - 注意 PHP 7.4+ 对空值处理更严格,
null或undefined变量传入会触发 notice,建议提前过滤或用?? ''提供默认值
前端 JS 里用 new Function 编译模板表达式,比正则 + eval 安全在哪
eval 会把字符串当作任意 JS 代码执行,作用域不可控,容易被注入恶意逻辑(比如 {{__proto__.constructor.constructor('alert(1)')()}})。而 new Function('scope', 'return ' + expr) 把表达式限制在传入的 scope 对象内,没有闭包、没有全局访问权,天然隔离。
但要注意几个硬约束:
立即学习“前端免费学习笔记(深入)”;
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
- 表达式必须是合法 JS 表达式,不能含语句(如
if、for),否则new Function构造失败 - 嵌套属性访问(如
user.profile.name)依赖scope是扁平对象,不是原始 HTML 字符串里直接写{{user.profile.name}}就能跑通——得先确保scope.user存在且是对象 - 缓存函数实例很重要,否则每次渲染都重新
new Function,V8 引擎无法优化,性能掉得明显;建议用WeakMap或字符串哈希做 key
VS Code 全局替换 HTML 模板变量,哪些地方一换就崩
Ctrl+Shift+H 是最快手段,但只适合纯文本场景。一旦占位符出现在属性值、注释、JS 字符串或跨标签内容里,就会出事。
典型翻车点:
- 替换
{{title}}时,顺手把<meta name="description" content="{{title}}">里的也换了——没问题;但如果模板里还有console.log('{{title}}');,JS 字符串也被替了,可能破坏语法 - 启用正则模式后没转义点号(
.),写成{{.*?}},结果匹配到<div class="card {{status}}"></div>中的{{status}},但也误吞了class="card "前面的空格甚至引号 - UTF-8 BOM 文件在某些旧版编辑器里识别为乱码,替换后出现 字符;建议先用 VS Code 右下角编码切换为 UTF-8(无 BOM)再操作
Python 用 BeautifulSoup 改 HTML 文本内容,为什么不能动属性值
BeautifulSoup 默认只遍历 text 节点,它设计目标就是“改人眼看到的文字”,所以 href、src、data- 这类属性值完全不在它的处理范围内。这是优点也是限制。
如果你确实要改属性,必须显式定位:
- 改所有
href:用soup.find_all(href=True),再对每个元素的.attrs['href'] = new_url - 改特定 class 下的
data-id:soup.select('.item[data-id]'),然后循环赋值 - 千万别用
soup.get_text()再塞回去——那会丢掉所有标签结构;要用.replace_with()或直接改.string - 记得排除
script和style标签:加条件if tag.parent.name not in ['script', 'style']
{{user_input}} 直接进 new Function,没做 escape 就渲染到 innerHTML,等于把防护全绕开了。安全不是加个转义函数就完事,而是从占位符设计、作用域隔离、输出通道三处同时卡死。


















