如何在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个:
- 正则表达式的问题:原正则里用了HTML实体
"代替双引号,导致无法匹配实际的双引号字符串;同时缺少sm修饰符——s让.匹配换行符,m让$匹配每行的结尾,保证单行注释能正确匹配到行尾。 - 变量名不一致:你定义的是
$html变量,但回调里用的是$js,导致实际处理的是未定义的变量(PHP会警告,且处理空内容)。 - 替换逻辑错误:原回调返回
"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
相关产品推荐
相关产品推荐

