一尘不染

正则表达式从C#中删除行注释

c#

我正在研究一个例程,以从某些C#代码中删除块 行注释。我看了网站上的其他示例,但没有找到我想要的 确切 答案。

我可以将此正则表达式与RegexOptions.Singleline完全匹配块注释(/ * comment * /):

(/\*[\w\W]*\*/)

我可以使用带有RegexOptions.Multiline的正则表达式来整体匹配行注释(// comment):

(//((?!\*/).)*)(?!\*/)[^\r\n]

注意:我使用的[^\r\n]不是,$因为$也包括\r在比赛中。

然而,这并不 十分 工作,我希望它的方式。

这是我要匹配的测试代码:

// remove whole line comments
bool broken = false; // remove partial line comments
if (broken == true)
{
    return "BROKEN";
}
/* remove block comments
else
{
    return "FIXED";
} // do not remove nested comments */ bool working = !broken;
return "NO COMMENT";

块表达式匹配

/* remove block comments
else
{
    return "FIXED";
} // do not remove nested comments */

很好,但是行表达式匹配

// remove whole line comments
// remove partial line comments

// do not remove nested comments

另外,如果我两次没有在行表达式中使用* /正向查找,它将与

// do not remove nested comments *

真的 不想要

我要的是将匹配字符,从与表达//,到行的末尾,但 包含*/之间//和行尾。

另外,只是为了满足我的好奇心,有人可以解释为什么我需要两次超前吗?
(//((?!\*/).)*)[^\r\n]并且(//(.)*)(?!\*/)[^\r\n]都将包括*,但(//((?!\*/).)*)(?!\*/)[^\r\n](//((?!\*/).)*(?!\*/))[^\r\n]不会。


阅读 346

收藏
2020-05-19

共1个答案

一尘不染

您的两个正则表达式(用于块和行注释)均存在错误。如果您愿意,我可以描述一下这些bug,但是我觉得如果编写新的bug可能会更有效率,尤其是因为我打算编写一个同时匹配两者的bug。

问题是,每次你有时间/*//和文字字符串“干扰”互相,它始终是一个开始:第一,优先。这非常方便,因为这正是正则表达式的工作方式:首先找到第一个匹配项。

因此,让我们定义一个与这四个标记匹配的正则表达式:

var blockComments = @"/\*(.*?)\*/";
var lineComments = @"//(.*?)\r?\n";
var strings = @"""((\\[^\n]|[^""\n])*)""";
var verbatimStrings = @"@(""[^""]*"")+";

要回答标题中的问题(带状注释),我们需要:

  • 用任何内容替换块注释
  • 用换行符替换行注释(因为正则表达式会吃掉换行符)
  • 将原义字符串保留在原处。

Regex.Replace 可以使用MatchEvaluator函数轻松做到这一点:

string noComments = Regex.Replace(input,
    blockComments + "|" + lineComments + "|" + strings + "|" + verbatimStrings,
    me => {
        if (me.Value.StartsWith("/*") || me.Value.StartsWith("//"))
            return me.Value.StartsWith("//") ? Environment.NewLine : "";
        // Keep the literal strings
        return me.Value;
    },
    RegexOptions.Singleline);

我在Holystream提供的所有示例以及我能想到的其他各种情况下运行了这段代码,它的工作原理很吸引人。如果您可以提供一个失败的示例,我们很乐意为您调整代码。

2020-05-19