【问题标题】:Removing comments using regex使用正则表达式删除评论
【发布时间】:2017-02-17 00:19:48
【问题描述】:

我正在构建一个解析器,我想从各个行中删除 cmets。例如,

variable = "some//thing" ////actual comment

评论标记是//。在这种情况下,variable 将包含"some//thing",其他所有内容都将被忽略。我计划使用正则表达式替换来做到这一点。目前我使用(".*"|[ \t])*(\/\/.*) 作为正则表达式。但是替换它会完全替换 "some//thing" ////actual comment

我不知道应该改用哪个正则表达式。感谢您的帮助。

附加信息 - 我正在使用带有 netcoreapp 1.1.0 的 C#

编辑 - 某些情况下可能只有 //line comment 之类的注释。字符串也可能包含转义引号。

【问题讨论】:

  • 您是在解析现有语言,还是这是自定义格式?
  • 这是一种自定义语言
  • This page might help? "[^"]*"|(//.*),但不包括转义引号 - 例如"some\"//thing"
  • 字符串也可能包含转义引号。我会尝试制作链接。
  • @KenY-N 我想出了这个"(?>[^\\\n""]+|\\.)*"|(\/\/.*)。虽然这确实可以处理转义引号,但让我们看看是否有人可以提出更强大的东西。

标签: c# regex


【解决方案1】:

这是丑陋的正则表达式模式。我相信它会运作良好。我已经用我能想到的每一个病态例子都试过了,包括包含语法错误的行。例如,一个带引号的字符串有太多引号,或者太少,或者有一个双引号,因此 not 被转义。并且在 cmets 中使用带引号的字符串,众所周知,当我想提醒自己替代方案时会这样做。

唯一会出错的情况是,如果在 看似 引用的字符串中有双斜杠,并且该字符串格式不正确,并且双斜杠在正确引用的部分之外合法地结束。从语法上讲,这使它成为一个有效的注释,即使不是程序员的意图。所以,从程序员的角度来看,这是错误的,但按照规则,它确实是一个注释。意思是,该模式似乎只会跳闸。

使用该模式时,将返回行的非注释部分。该模式中有一个换行符\n,以允许将其应用于整个文件。如果您的系统以其他方式解释换行符,您可能需要修改它,例如\r\r\n。要在单行模式下使用它,您可以选择删除它。它在单行版本的第 17 和 18 个字符处,在多行版本的第 5 行、第 6 和第 7 个打印字符上。但是,您可以放心地将它留在那里,因为在单行模式下它没有任何区别,而在多行模式下,它将为空白的代码行返回一个换行符,或者在第一列开始有注释。如果您将结果写入新文件,这将使原始版本和简化版本中的行号保持相同。便于比较。

此模式的一个主要警告:它使用在正则表达式引擎中具有不同级别支持的分组构造。我相信在这里使用,环顾四周,只有 .NET 和 PCRE 引擎才能接受 YMMV。它是第三类:(?(_condition_)_then_|_else_)_condition_ 模式被视为零宽度断言。如果模式匹配,则在尝试的匹配中使用_then_ 模式,否则使用_else_ 模式。如果没有这种结构,该模式会变得非常长,并且在我的一些病态测试用例中仍然失败。

这里展示的模式是正则表达式引擎需要看到的。我不是 C# 程序员,所以我不知道转义引用字符串的所有细微差别。将此模式放入您的代码中,以便正则表达式引擎正确看到所有反斜杠和引号仍然取决于您。或许 C# 有相当于 Perl 的 heredoc 语法。

这是要使用的单线模式:

^((?:(?:(?:[^"'/\n]|/(?!/))*)(?("(?=(?:\\\\|\\"|[^"])*"))(?:"(?:\\\\|\\"|[^"])*")|(?('(?=(?:\\\\|\\'|[^'])*'))(?:'(?:\\\\|\\'|[^'])*')|(?(/)|.))))*)

如果你想使用忽略模式空白选项,你可以使用这个版本:

(?x) # Turn on the ignore white space option
^( # Start the only capturing group
    (?: # A non-capturing group to allow for repeating the logic
        (?: # Capture either of the two options below
            [^"'/\n] # Capture everything not a single quote, double quote, a slash, or a newline
            | # OR
            /(?!/) # Capture a slash not followed by a slash [slash an negative look-ahead slash]
        )* # As many times as possible, even if none
        (?(" # Start a conditional match for double-quoted strings
                (?=(?:\\\\|\\"|[^"])*") # Followed by a properly closed double-quoted string
            ) # Then
            (?:"(?:\\\\|\\"|[^"])*") # Capture the whole double-quoted string
            | # Otherwise
            (?(' # Start a conditional match for single-quoted strings
                (?=(?:\\\\|\\'|[^'])*') # Followed by a properly closed single-quoted string
                ) # Then
                (?:'(?:\\\\|\\'|[^'])*') # Capture the whole double-quoted string
                | # Otherwise
                (?([^/]) # If next character is not a slash
                .) # Capture that character, it is either a single quote, or a double quote not part of a properly closed
            ) # end the conditional match for single-quoted strings
        ) # End the conditional match for double-quoted strings
    )* # Close the repeating non-capturing group, capturing as many times as possible, even if none
) # Close the only capturing group

这允许您的代码解释这个怪物,这样当其他人看到它时,或者在几个月后您必须自己处理它时,没有 WTF 时刻。我认为 cmets 解释得很好,但您可以随意更改它们。

如上所述,条件匹配分组的支持有限。它会失败的一个地方是您在之前的评论中链接到的网站。由于您使用的是 C#,因此我选择在可以处理这些构造的 .NET Regex Tester 中进行测试。它也包括一个很好的参考。鉴于侧面的正确选择,您可以测试上述任一版本,并对其进行试验。考虑到它的复杂性,我建议在某个地方针对您文件中的数据以及您可以想到的任何边缘案例和病理测试对其进行测试。

为了弥补这个小模式,有一个更大的模式用于测试电子邮件地址,它是 78 列 x 81 行,还有几十个字符。 (我建议使用或任何其他正则表达式来测试电子邮件地址。该工作的工具错误。)如果你想吓唬自己,请在ex-parrot 网站上查看它.我和那个无关!!

【讨论】:

  • 感谢您的努力,但您的正则表达式不会将 cmets 与 "qwe\" qwe" \\asd 等引号分开。现在我选择"(?>[^\\\n"]+|\\.)*"|(\/\/.*)(regex101.com/r/GxcvJz/6)。我也看了链接。那个正则表达式是一个怪物。再次感谢您的努力!
  • 我的错误。我使用反斜杠而不是正斜杠。您的解决方案完美运行!另外,它省去了手动分离字符串和 cmets 的麻烦。非常感谢!
  • 如果您确实发现了一些无法正常工作的边缘情况,请发表评论,以便我可以尝试进一步调整。我认为它捕获了所有的病态案例,甚至是语法上无效的案例,除了错误配对的引号。我打算将它保存在我的图书馆中,并希望它尽可能好。
  • GitHub 存储库已被移动。仍然命名为comment_removal
【解决方案2】:

"[^"\\]*(?:\\[\W\w][^"\\]*)*"|(\/\/.*)

标志:全球

匹配完整的字符串或评论。

第 1 组:评论。

因此,如果没有评论,请替换为相同的匹配文本。否则,请在评论本身上做你的事情。

【讨论】:

  • link相比如何?哪个更好?
猜你喜欢
  • 2015-04-09
  • 1970-01-01
  • 2011-07-21
  • 2017-08-04
  • 2017-01-10
  • 1970-01-01
  • 2019-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多