如何用preg_replace_callback隔离HTML中的JavaScript代码?
解决PHP中用preg_replace_callback处理HTML内JS代码的问题
问题分析
你的正则存在两个核心问题:
- 未限定
on*属性的匹配范围,导致误匹配标签外的文本内容 - 用
(*SKIP)(*F)跳过了<script>标签,无法处理其中的JS代码
解决方案(分两步处理)
1. 先处理<script>标签内的JS代码
匹配完整的<script>标签,保留标签属性,仅替换内部的JS代码:
// 处理script标签内的代码 $html = preg_replace_callback('/<script\b(.*?)>(.*?)<\/script\b.*?>/ism', function($matches) { // 保留原script标签的属性,替换内部代码为处理后结果 return "<script{$matches[1]}>" . myFunction($matches[2]) . "</script>"; }, $html);
2. 处理HTML标签内的on*事件属性
通过正则限定仅匹配标签<>范围内的on*属性,跳过标签外的文本内容:
// 处理标签内的on事件属性 $regex = '/(?:(?!<)[^<]|<[^>]*?>)(*SKIP)(*F)|\bon(\w+)=([\'"])(.*?)\2/ism'; $html = preg_replace_callback($regex, function($matches) { return "on{$matches[1]}{$matches[2]}" . myFunction($matches[3]) . "{$matches[2]}"; }, $html);
完整代码示例
假设myFunction是你的JS代码处理函数(示例为替换特定内容):
function myFunction($jsCode) { // 示例:将abc()替换为processed_abc() return str_replace('abc()', 'processed_abc()', $jsCode); } $html= "<div id='content' onClick='abc()'>Lorem On='abc' ipsum on to</div> <input id='a' type='range'> <input id='b' type='range'> <script>abc();</script>"; // 第一步处理script标签 $html = preg_replace_callback('/<script\b(.*?)>(.*?)<\/script\b.*?>/ism', function($matches) { return "<script{$matches[1]}>" . myFunction($matches[2]) . "</script>"; }, $html); // 第二步处理on事件属性 $regex = '/(?:(?!<)[^<]|<[^>]*?>)(*SKIP)(*F)|\bon(\w+)=([\'"])(.*?)\2/ism'; $html = preg_replace_callback($regex, function($matches) { return "on{$matches[1]}{$matches[2]}" . myFunction($matches[3]) . "{$matches[2]}"; }, $html); echo $html;
最终输出
<div id='content' onClick='processed_abc()'>Lorem On='abc' ipsum on to</div> <input id='a' type='range'> <input id='b' type='range'> <script>processed_abc();</script>
关键逻辑说明
- 拆分两步处理,避免正则逻辑过于复杂
- 处理
on*属性时,用(*SKIP)(*F)跳过所有标签外的内容,确保仅匹配标签属性中的事件 - 处理
<script>标签时,保留原标签的属性(如type="text/javascript"),仅替换内部JS代码
内容的提问来源于stack exchange,提问作者abe1432181
相关产品推荐
相关产品推荐

