我正在寻找一种使用 PHP 去除 HTML 代码中所有 javascript 注释的解决方案。
我想删除仅Javascript注释(而不是HTML注释等)。我认为正则表达式不是一个解决方案,因为它无法理解是否是真正的注释或字符串的一部分。示例:
<script>
// This is a comment
/* This is another comment */
// The following is not a comment
var src="//google.com";
</script>
有办法吗?非常感谢提前
首先要做的事情:您需要提取脚本标签的内容。为此,请使用 DOMDocument:
$dom = new DOMDocument;
$dom->loadHTML($html);
$scriptNodes = $dom->getElementsByTagName('script');
第二步包括删除每个脚本节点的所有 javascript 注释。
如果需要,您可以使用第三方 JavaScript 解析器,但也可以使用正则表达式来实现。您所需要做的就是防止考虑报价之间的部分。
为此,您必须搜索引号之间的第一部分并丢弃它们。使用 javascript 做到这一点的唯一困难是引号可以位于正则表达式模式内,例如:
/pattern " with a quote/
所以你也需要找到模式来防止任何错误。
图案示例:
$pattern = <<<'EOD'
~
(?(DEFINE)
(?<squoted> ' [^'\n\\]*+ (?: \\. [^'\n\\]* )*+ ' )
(?<dquoted> " [^"\n\\]*+ (?: \\. [^"\n\\]* )*+ " )
(?<tquoted> ` [^`\\]*+ (?s: \\. [^`\\]*)*+ ` )
(?<quoted> \g<squoted> | \g<dquoted> | \g<tquoted> )
(?<scomment> // \N* )
(?<mcomment> /\* [^*]*+ (?: \*+ (?!/) [^*]* )*+ \*/ )
(?<comment> \g<scomment> | \g<mcomment> )
(?<pattern> / [^\n/*] [^\n/\\]*+ (?>\\.[^\n/\\]*)* / [gimuy]* )
)
(?=[[(:,=/"'`])
(?|
\g<quoted> (*SKIP)(*FAIL)
|
( [[(:,=] \s* ) (*SKIP) (?: \g<comment> \s* )*+ ( \g<pattern> )
|
( \g<pattern> \s* ) (?: \g<comment> \s* )*+
( \. \s* ) (?:\g<comment> \s* )*+ ([A-Za-z_]\w*)
|
\g<comment>
)
~x
EOD;
然后替换各个脚本节点的内容:
foreach ($scriptNodes as $scriptNode) {
$scriptNode->nodeValue = preg_replace($pattern, '$9${10}${11}', $scriptNode->nodeValue);
}
$html = $dom->saveHTML();
图案详情:
((?DEFINE)...)
是您可以放置稍后需要的所有子模式定义的区域。 “真正的”模式开始于之后。
(?<name>...)
被命名为子模式。它与捕获组相同,只是您可以使用其名称(如\g<name>
)而不是其编号来引用它。
*+
是 所有格量词
\N
表示不是换行符的字符
(?=[[(:,=/"'])</code> is a [lookahead][3] that checks if the next character is one of these <code>[ ( : , = / " '
。此测试的目的是防止在字符不同时测试以下交替的每个分支。如果删除它,模式将发挥相同的作用,只是快速跳过字符串中无用的位置。
])</code> is a [lookahead][3] that checks if the next character is one of these <code>[ ( : , = / " '
是回溯控制动词。当该模式在其之后失败时,将不会尝试之前匹配的所有位置。
(*SKIP)
也是一个回溯控制动词,强制模式失败。
(*FAIL)
是分支重置组。在其中,捕获组在每个分支中分别具有相同的数字(对于此模式为 9 和 10)。
使用此功能
(?|..(..)..(..)..|..(..)..(..)..)
使用这两个链接 http://trinithis.awardspace.com/commentStripper/stripper.html
http://james.padolsey.com/javascript/removing-comments-in-javascript/
进一步参考检查它Javascript注释剥离器
此正则表达式适用于您的示例:
function removeComments(str) {
str = ('__' + str + '__').split('');
var mode = {
singleQuote: false,
doubleQuote: false,
regex: false,
blockComment: false,
lineComment: false,
condComp: false
};
for (var i = 0, l = str.length; i < l; i++) {
if (mode.regex) {
if (str[i] === '/' && str[i-1] !== '\') {
mode.regex = false;
}
continue;
}
if (mode.singleQuote) {
if (str[i] === "'" && str[i-1] !== '\') {
mode.singleQuote = false;
}
continue;
}
if (mode.doubleQuote) {
if (str[i] === '"' && str[i-1] !== '\') {
mode.doubleQuote = false;
}
continue;
}
if (mode.blockComment) {
if (str[i] === '*' && str[i+1] === '/') {
str[i+1] = '';
mode.blockComment = false;
}
str[i] = '';
continue;
}
if (mode.lineComment) {
if (str[i+1] === 'n' || str[i+1] === 'r') {
mode.lineComment = false;
}
str[i] = '';
continue;
}
if (mode.condComp) {
if (str[i-2] === '@' && str[i-1] === '*' && str[i] === '/') {
mode.condComp = false;
}
continue;
}
mode.doubleQuote = str[i] === '"';
mode.singleQuote = str[i] === "'";
if (str[i] === '/') {
if (str[i+1] === '*' && str[i+2] === '@') {
mode.condComp = true;
continue;
}
if (str[i+1] === '*') {
str[i] = '';
mode.blockComment = true;
continue;
}
if (str[i+1] === '/') {
str[i] = '';
mode.lineComment = true;
continue;
}
mode.regex = true;
}
}
return str.join('').slice(2, -2);
}
PHP代码:
^\/(?:\/|\*).*
或者也许这样,来验证
$re = "/^\\/(?:\\/|\\*).*/m";
$str = "<script>\n\n// This is a comment\n/* This is another comment */\n\n// The following is not a comment\nvar src=\"//google.com\"; \n\n</script>";
preg_match_all($re, $str, $matches);
:
*/
PHP代码:
^\/{2}.*|\/\*.*\*\/$