全面的RegExp删除JavaScript注释

Comprehensive RegExp to remove JavaScript comments

本文关键字:JavaScript 注释 删除 RegExp      更新时间:2023-09-26

我需要用一个正则表达式可靠地删除所有JavaScript注释。

我已经搜索了StackOverflow和其他网站,但没有一个考虑到交替引号,多行评论,字符串内的评论,正则表达式等。

是否有正则表达式可以删除注释:

var test = [
    "// Code",
    '// Code',
    "'// Code",
    '"// Code',
    //" Comment",
    //' Comment',
    /* Comment */
    // Comment /* Comment
    /* Comment
     Comment // */ "Code",
    "Code",
    "/* Code */",
    "/* Code",
    "Code */",
    '/* Code */',
    '/* Code',
    'Code */',
    /* Comment
    "Comment",
    Comment */ "Code",
    /Code'/*/,
    "Code */"
]

这里有一个jsbin或jsfiddle来测试它

我喜欢挑战:)

这是我的工作解决方案:

/((["'])(?:''['s'S]|.)*?'2|'/(?![*'/])(?:''.|'[(?:''.|.)']|.)*?'/)|'/'/.*?$|'/'*['s'S]*?'*'//gm

替换为$1

点击此处:http://jsfiddle.net/LucasTrz/DtGq8/6/

当然,正如无数次指出的那样,一个合适的解析器可能会更好,但仍然…

注意:我用的是正则表达式而不是字符串,太多的转义会破坏你的大脑。


<标题>分解h1> 保留的部分
(["'])(?:''['s'S]|.)*?'2                   <-- strings
'/(?![*'/])(?:''.|'[(?:''.|.)']|.)*?'/     <-- regex literals
字符串

    ["']              match a quote and capture it
    (?:''['s'S]|.)*?  match escaped characters or unescpaed characters, don't capture
    '2                match the same type of quote as the one that opened the string
<<h3> Regex文字/h3>
    '/                          match a forward slash
    (?![*'/])                   ... not followed by a * or / (that would start a comment)
    (?:''.|'[(?:''.|.)']|.)*?   match any sequence of escaped/unescaped text, or a regex character class
    '/                          ... until the closing slash

要删除的部分

|'/'/.*?$              <-- line comments
|'/'*['s'S]*?'*'/      <-- inline comments

行评论

    '/'/         match two forward slashes
    .*?$         then everything until the end of the line
内联注释

    '/'*         match /*
    ['s'S]*?     then as few as possible of anything, see note below
    '*'/         match */

我不得不使用['s'S]而不是.,因为不幸的是JavaScript不支持regex s修饰符(单行-这个允许.匹配换行符)

这个正则表达式将适用于以下情况:

  • 字符类中包含/的正则表达式模式:/[/]/
  • 字符串中的转义换行

最终boss战

只是为了好玩…这是令人瞠目的硬核版本:

/((["'])(?:''['s'S]|.)*?'2|(?:[^'w's]|^)'s*'/(?![*'/])(?:''.|'[(?:''.|.)']|.)*?'/(?=[gmiy]{0,4}'s*(?![*'/])(?:'W|$)))|'/'/.*?$|'/'*['s'S]*?'*'//gm

这增加了以下扭曲边缘情况(fiddle, regex101):

Code = /* Comment */ /Code regex/g  ; // Comment
Code = Code / Code /* Comment */ /g  ; // Comment    
Code = /Code regex/g /* Comment */  ; // Comment

这是高度启发式代码,您可能不应该使用它(甚至比之前的regex更少),只是让边缘情况爆发。

首先,我建议使用适当的JavaScript解析器来完成此操作。在JavaScript

中查看前面的问题&A: JavaScript解析器

对于您提供的输入1,这里有一个可能有效的解决方案:

匹配模式:

/("(?:[^'r'n''"]|''.)*"|'(?:[^'r'n''']|''.)*'|'/[^*'/]([^'''/]|''.)*'/[gm]*)|'/'/[^'r'n]*|'/'*['s'S]*?'*'//g

下面是该模式的细分:

/
  (                                     # start match group 1
      "(?:[^'r'n''"]|''.)*"             #   match a double quoted string
    | '(?:[^'r'n''']|''.)*'             #   match a single quoted string
    | '/[^*'/]([^'''/]|''.)*'/[gm]*     #   match a regex literal
  )                                     # end match group 1
  | '/'/[^'r'n]*                        # match a single line break
  | '/'*['s'S]*?'*'/                    # match a multi-line break
/g

并将其替换为$1(匹配组1)。这里的技巧是除了注释之外的任何内容都在组1中匹配,它再次被替换为自身,但注释被替换为空字符串。

下面是一个regexr示例,演示了以下替换:

  var test = [
      "// Code",
      '// Code',
      "'// Code",
      '"// Code',


       "Code",
      "Code",
      "/* Code */",
      "/* Code",
      "Code */",
      '/* Code */',
      '/* Code',
      'Code */',
       "Code",
      /Code'/*/,
      "Code */"
  ]

1同样,解析器是一种方法,因为regex字面值可能与除法操作符混淆。如果源代码中有var x = a / b / g;这样的赋值,上面的解决方案就会失效!

我建议您考虑使用JavaScript解析器本身解析JavaScript,然后利用解析器API剥离您不想要的内容。我个人没有这样做过,但是正则表达式应该局限于常规内容,我怀疑JS会陷入这种情况。

这里有一些好地方可以看。

JavaScript解析器

是否有任何正则表达式可以删除注释

。您不能构建一个匹配注释的正则表达式(这样您就可以简单地用空字符串替换匹配),因为如果不向后看,就不可能确定//"是注释还是字符串文字的结尾。

您可以使用正则表达式作为标记器(您"只"需要处理字符串字面值、正则表达式字面值和两种类型的注释),但我建议使用成熟的JavaScript解析器,它们是免费提供的。

test.replace (/(/* ([' s ' s] ?)*/)|(//(.)美元)/通用,");