使用正则表达式从源文件中删除注释

Lyn*_*ite 25 python regex string

我正在编写一个程序来自动编写一些C代码,(我正在编写将字符串解析为具有相同名称的枚举)C对字符串的处理并不是那么好.所以有些人一直在唠叨我试试python.

我创建了一个应该删除C风格/* COMMENT *///COMMENT 字符串的函数:这是代码:

def removeComments(string):
    re.sub(re.compile("/\*.*?\*/",re.DOTALL ) ,"" ,string) # remove all occurance streamed comments (/*COMMENT */) from string
    re.sub(re.compile("//.*?\n" ) ,"" ,string) # remove all occurance singleline comments (//COMMENT\n ) from string
Run Code Online (Sandbox Code Playgroud)

所以我尝试了这个代码.

str="/* spam * spam */ eggs"
removeComments(str)
print str
Run Code Online (Sandbox Code Playgroud)

它显然没有做任何事情.

关于我做错了什么的任何建议?

有一种说法,我听过几次:

如果您遇到问题而尝试使用Regex解决问题,最终会遇到两个问题.


编辑:回顾这几年后.(经过更多的解析经验)

我认为正则表达式可能是正确的解决方案.而这里使用的简单正则表达"足够好".我可能没有在这个问题上强调这一点.这是针对单个特定文件的.那没有棘手的情况.我认为保持文件解析对于正则表达式而言要简单得多,而不是将正则表达式复杂化为不可读的符号汤.

Onu*_*rım 34

已经给出了许多答案但是;
怎么样"//comment-like strings inside quotes"

OP正在询问如何使用正则表达式来做到这一点; 所以:

def remove_comments(string):
    pattern = r"(\".*?\"|\'.*?\')|(/\*.*?\*/|//[^\r\n]*$)"
    # first group captures quoted strings (double or single)
    # second group captures comments (//single-line or /* multi-line */)
    regex = re.compile(pattern, re.MULTILINE|re.DOTALL)
    def _replacer(match):
        # if the 2nd group (capturing comments) is not None,
        # it means we have captured a non-quoted (real) comment string.
        if match.group(2) is not None:
            return "" # so we will return empty to remove the comment
        else: # otherwise, we will return the 1st group
            return match.group(1) # captured quoted-string
    return regex.sub(_replacer, string)
Run Code Online (Sandbox Code Playgroud)

删除:

  • /* multi-line comments */
  • // single-line comments

不会删除:

  • String var1 = "this is /* not a comment. */";
  • char *var2 = "this is // not a comment, either.";
  • url = 'http://not.comment.com';

注意:这也适用于Javascript源代码.

  • 这是一个改进的正则表达式,它可以做一个负面的观察,以避免转义引号.`R "(\"*(<\\)\"?|?!\ '*(<\\)\.?!')|(/\*.*?\*/ | // [^\r \n]*$)"` (5认同)
  • @ishmael`“带有反斜杠的字符串\\”/*删除这个*/“...”`怎么样? (2认同)

msa*_*ers 29

re.sub 返回一个字符串,因此将代码更改为以下内容将得到结果:

def removeComments(string):
    string = re.sub(re.compile("/\*.*?\*/",re.DOTALL ) ,"" ,string) # remove all occurrences streamed comments (/*COMMENT */) from string
    string = re.sub(re.compile("//.*?\n" ) ,"" ,string) # remove all occurrence single-line comments (//COMMENT\n ) from string
    return string
Run Code Online (Sandbox Code Playgroud)

  • `char*note ="你可以用//";哎呀来做一行评论. (4认同)

jat*_*ism 16

我建议使用像SimpleParsePyParsing这样的REAL解析器.SimpleParse要求您实际知道EBNF,但速度非常快.PyParsing有类似EBNF的语法,但它适用于Python,并且可以轻松构建功能强大的解析器.

编辑:

以下是在此上下文中使用PyParsing是多么容易的示例:

>>> test = '/* spam * spam */ eggs'
>>> import pyparsing
>>> comment = pyparsing.nestedExpr("/*", "*/").suppress()
>>> print comment.transformString(test)         
' eggs'
Run Code Online (Sandbox Code Playgroud)

以下是使用单行和多行注释的更复杂示例.

之前:

/*
 * multiline comments
 * abc 2323jklj
 * this is the worst C code ever!!
*/
void
do_stuff ( int shoe, short foot ) {
    /* this is a comment
     * multiline again! 
     */
    exciting_function(whee);
} /* extraneous comment */
Run Code Online (Sandbox Code Playgroud)

后:

>>> print comment.transformString(code)   

void
do_stuff ( int shoe, short foot ) {

     exciting_function(whee);
} 
Run Code Online (Sandbox Code Playgroud)

它会在删除评论的地方留下额外的换行符,但这可以解决.


小智 8

在 Jathanism 之后,找到了另一个 pyparsing 解决方案。

import pyparsing

test = """
/* Code my code
xx to remove comments in C++
or C or python */

include <iostream> // Some comment

int main (){
    cout << "hello world" << std::endl; // comment
}
"""
commentFilter = pyparsing.cppStyleComment.suppress()
# To filter python style comment, use
# commentFilter = pyparsing.pythonStyleComment.suppress()
# To filter C style comment, use
# commentFilter = pyparsing.cStyleComment.suppress()

newtest = commentFilter.transformString(test)
print(newest)
Run Code Online (Sandbox Code Playgroud)

产生以下输出:

include <iostream> 

int main (){
    cout << "hello world" << std::endl; 
}
Run Code Online (Sandbox Code Playgroud)

还可以使用pythonStyleComment、javaStyleComment、cppStyleComment。发现它非常有用。