Python 正则表达式问题 : stripping multi-line comments but maintaining a line break

标签 python regex parsing comments

我正在解析一个源代码文件,我想删除所有行注释(即以“//”开头)和多行注释(即/..../) .但是,如果多行注释中至少有一个换行符 (\n),我希望输出只有一个换行符。

例如代码:

qwe /* 123
456 
789 */ asd

应该完全变成:

qwe
asd

而不是“qweasd”或:

qwe

asd

这样做的最佳方式是什么? 谢谢


编辑: 测试示例代码:

comments_test = "hello // comment\n"+\
                "line 2 /* a comment */\n"+\
                "line 3 /* a comment*/ /*comment*/\n"+\
                "line 4 /* a comment\n"+\
                "continuation of a comment*/ line 5\n"+\
                "/* comment */line 6\n"+\
                "line 7 /*********\n"+\
                "********************\n"+\
                "**************/\n"+\
                "line ?? /*********\n"+\
                "********************\n"+\
                "********************\n"+\
                "********************\n"+\
                "********************\n"+\
                "**************/\n"+\
                "line ??"

预期结果:

hello 
line 2 
line 3  
line 4
line 5
line 6
line 7
line ??
line ??

最佳答案

comment_re = re.compile(
    r'(^)?[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?',
    re.DOTALL | re.MULTILINE
)

def comment_replacer(match):
    start,mid,end = match.group(1,2,3)
    if mid is None:
        # single line comment
        return ''
    elif start is not None or end is not None:
        # multi line comment at start or end of a line
        return ''
    elif '\n' in mid:
        # multi line comment with line break
        return '\n'
    else:
        # multi line comment without line break
        return ' '

def remove_comments(text):
    return comment_re.sub(comment_replacer, text)
  • (^)? 将匹配注释从行首开始的情况,只要使用 MULTILINE 标志即可。
  • [^\S\n] 将匹配除换行符之外的任何空白字符。如果评论从它自己的行开始,我们不想匹配换行符。
  • /\*(.*?)\*/ 将匹配多行注释并捕获内容。惰性匹配,因此我们不会匹配两个或多个评论。 DOTALL-flag 使 . 匹配换行符。
  • //[^\n] 将匹配单行注释。不能使用 . 因为 DOTALL-flag.
  • ($)? 将在注释停在行尾时匹配,只要使用 MULTILINE 标志即可。

例子:

>>> s = ("qwe /* 123\n"
         "456\n"
         "789 */ asd /* 123 */ zxc\n"
         "rty // fgh\n")
>>> print '"' + '"\n"'.join(
...     remove_comments(s).splitlines()
... ) + '"'
"qwe"
"asd zxc"
"rty"
>>> comments_test = ("hello // comment\n"
...                  "line 2 /* a comment */\n"
...                  "line 3 /* a comment*/ /*comment*/\n"
...                  "line 4 /* a comment\n"
...                  "continuation of a comment*/ line 5\n"
...                  "/* comment */line 6\n"
...                  "line 7 /*********\n"
...                  "********************\n"
...                  "**************/\n"
...                  "line ?? /*********\n"
...                  "********************\n"
...                  "********************\n"
...                  "********************\n"
...                  "********************\n"
...                  "**************/\n")
>>> print '"' + '"\n"'.join(
...     remove_comments(comments_test).splitlines()
... ) + '"'
"hello"
"line 2"
"line 3 "
"line 4"
"line 5"
"line 6"
"line 7"
"line ??"
"line ??"

编辑:

  • 更新到新规范。
  • 添加了另一个示例。

关于Python 正则表达式问题 : stripping multi-line comments but maintaining a line break,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/844681/

相关文章:

ruby-on-rails - 键值对的正则表达式 Markdown 字符串

python - 使用正则表达式解析带有单位的值范围

c - 尝试解析文档并存储节点信息,不知道为什么会出现段错误

c++ - 如何基于CFG验证输入?

python - pip install 无法从 Azure Ubuntu 找到版本

Python AES 256 CBC 加密 - ValueError : Incorrect AES key length

python - 多行 csv 字段和 Python next(file)

python - Cron 失败并显示消息 Superset : command not found

javascript - 为什么 split 函数会在下面的例子中创建三个子字符串而不是两个?

xcode - 在框架模块 'Bolts BFCancellationToken' 中包含非模块化 header