删除PHP中的所有REAL Javascript注释

时间:2015-06-01 12:14:56

标签: javascript php regex comments

我正在寻找一种解决方案,使用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>

有办法吗?非常感谢提前

3 个答案:

答案 0 :(得分:0)

使用此功能

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);
}

使用这两个链接 http://trinithis.awardspace.com/commentStripper/stripper.html

http://james.padolsey.com/javascript/removing-comments-in-javascript/

进一步参考检查Javascript comment stripper

答案 1 :(得分:0)

要做的第一件事:您需要提取脚本标记的内容。为此,请使用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\\]* )*+ " )
    (?<quoted>  \g<squoted> | \g<dquoted> )

    (?<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, '$8$9${10}', $scriptNode->nodeValue);
}

$html = $dom->saveHTML();

demo

模式细节:

((?DEFINE)...)是一个可以放置稍后需要的所有子模式定义的区域。 &#34;真实&#34;模式开始于。

(?<name>...)被命名为子模式。它与捕获组相同,只是您可以使用其名称(例如此\g<name>)而不是其编号来引用它。

*+possessive quantifiers

\N表示不是换行符的字符

(?=[[(:,=/"'])lookahead,用于检查下一个字符是否为[ ( : , = / " '之一。此测试的目的是防止在角色不同时测试以下交替的每个分支。如果你删除它,模式将工作相同,它只是为了快速跳过无用的表演位置。

(*SKIP)是一个回溯控制动词。当模式在它之后失败时,所有位置都会在它被尝试之前匹配。

(*FAIL)也是一个回溯控制动词,并强制模式失败。

(?|..(..)..(..)..|..(..)..(..)..)是分支重置组。在其中,捕获组在每个分支中分别具有相同的数字(此模式为8和9)

答案 2 :(得分:0)

此RegExp适用于您的示例:

^\/(?:\/|\*).*

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);

DEMO

或者也许这样,验证*/

^\/{2}.*|\/\*.*\*\/$

PHP代码:

$re = "/^\\/{2}.*|\\/\\*.*\\*\\/$/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);

DEMO2