You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP中实现检测并移除JavaScript注释的正则表达式

问题描述

我有一个正则表达式,能检测JavaScript的//单行注释和/* ... */多行注释,同时会忽略引号内的注释内容,也能处理.replace(/'/...这类场景,表现没问题。但我不知道怎么在PHP里用这个正则移除检测到的注释。我试了preg_replace_callback,但没得到预期结果。

我的代码
$js = <<<'PATTERN'
doSomething('aaaaa//cccccccc'); // c1ccccccc
/* c2cc' cc'ccc */
doSomething2(111, 222, 333); // c3ccccccc
abc.replace(/'/g, 'aaaaaa//aaaaa'); /* c4ccccccc */
abc.replace(/"/g, 'aaaaaaa'); /* c5ccccccc */
doSomething("<div>aaaaaaaa//aaaaaaaaaaaaa aaaaaaa aaaaaaa</div>",1234);// c6ccccccc
doSomething('<div>aaaaaaaa//aaaaaaaaaaaaa aaaaaaa aaaaaaa</div>',1234);// c7ccccccc
PATTERN;

$regex = <<<'PATTERN2'
~((["'])(?:\\[\s\S]|.)*?\2|(?:[^\w\s]|^)\s*/(?![*/])(?:\\.|\[(?:\\.|.)\]|.)*?/(?=[gmiy]{0,4}\s*(?![*/])(?:\W|$)))|//.*?$|/\*[\s\S]*?\*/~sm
PATTERN2;

$newJS = preg_replace_callback($regex
            , function ($m) {
                $match = $m[0];
                if (str_starts_with($match, '/*') || str_starts_with($match, '//')) {
                    return '';
                }
                return $match;
            }, $js);

echo $newJS;
原执行结果
doSomething('aaaaa//cccccccc'); // c1ccccccc
xx
doSomething2(111, 222, 333); // c3ccccccc
abc.replace(/'/g, 'aaaaaa//aaaaa'); xx
abc.replace(/"/g, 'aaaaaaa'); xx
doSomething("<div>aaaaaaaa//aaaaaaaaaaaaa aaaaaaa aaaaaaa</div>",1234);// c6ccccccc
doSomething('<div>aaaaaaaa//aaaaaaaaaaaaa aaaaaaa aaaaaaa</div>',1234);xx
正确实现方案

你遇到的问题主要有3个:

  1. 正则表达式的问题:原正则里用了HTML实体&quot;代替双引号,导致无法匹配实际的双引号字符串;同时缺少sm修饰符——s让.匹配换行符,m让$匹配每行的结尾,保证单行注释能正确匹配到行尾。
  2. 变量名不一致:你定义的是$html变量,但回调里用的是$js,导致实际处理的是未定义的变量(PHP会警告,且处理空内容)。
  3. 替换逻辑错误:原回调返回"xx"而不是空字符串,这只是替换成占位符,而非移除注释。

修正后的完整代码如上,执行后会得到预期结果:

doSomething('aaaaa//cccccccc'); 

doSomething2(111, 222, 333); 
abc.replace(/'/g, 'aaaaaa//aaaaa'); 
abc.replace(/"/g, 'aaaaaaa'); 
doSomething("<div>aaaaaaaa//aaaaaaaaaaaaa aaaaaaa aaaaaaa</div>",1234);
doSomething('<div>aaaaaaaa//aaaaaaaaaaaaa aaaaaaa aaaaaaa</div>',1234);

另外,正则里的分组逻辑是:第一个大括号内的内容是需要保留的(字符串、正则表达式字面量),后面的两个分支是需要移除的注释,也可以通过判断分组是否为空来更精准处理:

$newJS = preg_replace_callback($regex, function ($m) {
    // 如果第一个分组有内容(说明是字符串或正则),返回原内容
    if (!empty($m[1])) {
        return $m[1];
    }
    // 否则是注释,返回空
    return '';
}, $js);

这种方式更可靠,避免因为注释内容的特殊开头导致误判。

内容的提问来源于stack exchange,提问作者abe1432181

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 19:25:20