将单行 JavaScript 注释 (//) 与 re 匹配

Posted

技术标签:

【中文标题】将单行 JavaScript 注释 (//) 与 re 匹配【英文标题】:Matching one-line JavaScript comments (//) with re 【发布时间】:2011-01-09 07:57:39 【问题描述】:

我想使用 python 的 re 模块从(大部分是有效的)javascript 中过滤掉(大部分是单行的)cmets。例如:

// this is a comment
var x = 2 // and this is a comment too
var url = "http://www.google.com/" // and "this" too
url += 'but // this is not a comment' // however this one is
url += 'this "is not a comment' + " and ' neither is this " // only this

我现在尝试了半个多小时,但没有任何成功。谁能帮帮我?

编辑 1

foo = 'http://***.com/' // these // are // comments // too //

编辑 2

bar = 'http://no.comments.com/'

【问题讨论】:

此时,您应该考虑使用适当的解析器,而不是尝试破解正则表达式。 谢谢 Anon。如果我不能很快想出一个正则表达式,我会去找一个解析器。也许是蜘蛛猴? 【参考方案1】:

我的正则表达式能力有点过时了,所以我用你的问题来更新我记得的东西。 它变成了一个相当大的正则表达式,主要是因为我还想过滤多行 cmets。

import re

reexpr = r"""
    (                           # Capture code
        "(?:\\.|[^"\\])*"       # String literal
        |
        '(?:\\.|[^'\\])*'       # String literal
        |
        (?:[^/\n"']|/[^/*\n"'])+ # Any code besides newlines or string literals
        |
        \n                      # Newline
    )|
    (/\*  (?:[^*]|\*[^/])*   \*/)        # Multi-line comment
    |
    (?://(.*)$)                 # Comment
    $"""
rx = re.compile(reexpr, re.VERBOSE + re.MULTILINE)

这个正则表达式匹配三个不同的子组。一个用于代码,两个用于注释内容。 以下是如何提取这些的示例。

code = r"""// this is a comment
var x = 2 * 4 // and this is a comment too
var url = "http://www.google.com/" // and "this" too
url += 'but // this is not a comment' // however this one is
url += 'this "is not a comment' + " and ' neither is this " // only this

bar = 'http://no.comments.com/' // these // are // comments
bar = 'text // string \' no // more //\\' // comments
bar = 'http://no.comments.com/'
bar = /var/ // comment

/* comment 1 */
bar = open() /* comment 2 */
bar = open() /* comment 2b */// another comment
bar = open( /* comment 3 */ file) // another comment 
"""

parts = rx.findall(code)
print '*' * 80, '\nCode:\n\n', '\n'.join([x[0] for x in parts if x[0].strip()])
print '*' * 80, '\nMulti line comments:\n\n', '\n'.join([x[1] for x in parts if x[1].strip()])
print '*' * 80, '\nOne line comments:\n\n', '\n'.join([x[2] for x in parts if x[2].strip()])

【讨论】:

哇,这甚至比问题提前了一步,但这正是我所需要的!非常感谢您花时间解决这个问题! 我编辑了正则表达式,因为它与 'x = 4 * 5' 中的 '*' 不匹配,变成了 'x = 4 5)' 不适用于/* / *//* // */。修复:将 /\\* (?:\\*?[^/]|\n)* \\*/ 替换为 /\\* (?:[^*]|\\*[^/])* \\*/ 谢谢 Gumbo,我已经更改了正则表达式。【参考方案2】:

如果你有明确的分号,它可能更容易解析。

无论如何,这是可行的:

import re

rx = re.compile(r'.*(//(.*))$')

lines = ["// this is a comment", 
    "var x = 2 // and this is a comment too",
    """var url = "http://www.google.com/" // and "this" too""",
    """url += 'but // this is not a comment' // however this one is""",
    """url += 'this "is not a comment' + " and ' neither is this " // only this""",]

for line in lines: 
    print rx.match(line).groups()

以上输出:

('// this is a comment', ' this is a comment')
('// and this is a comment too', ' and this is a comment too')
('// and "this" too', ' and "this" too')
('// however this one is', ' however this one is')
('// only this', ' only this')

我不确定您在 删除 cmets 后对 javascript 做了什么,但 JSMin 可能会有所帮助。无论如何,它可以很好地删除 cmets,并且有一个 implementation in python。

【讨论】:

谢谢,这绝对是 +1。现在让我稍微修改一下我的问题:) 另外,JavaScript 不是我写的,所以很遗憾我不能保证明确的分号... 嗯,不,这只有在行尾总是有注释并且注释本身没有 // 时才有效。 var url = "http://www"// comments are started with // 都会失败。 @Thomas 好吧,它适用于指定的输入。正如@Anon 提到的,这里需要一个真正的解析器来正确捕获所有内容。 谢谢,JSMin 的 Python 实现现在可以满足我的需要。

以上是关于将单行 JavaScript 注释 (//) 与 re 匹配的主要内容,如果未能解决你的问题,请参考以下文章

0087 JavaScript注释

JavaScript 注释以及输入输出语句

JavaScript 注释以及输入输出语句

JavaScript-- 注释 & 变量 & 游览器调试使用

JavaScript 注释规范

前端开发规范Javascript