我正在编写一个例程来从一些C#代码中删除块或行注释.我查看了网站上的其他示例,但没有找到我正在寻找的确切答案.
我可以使用这个正则表达式与RegexOptions.Singleline完全匹配块注释(/*comment*/):
(/\*[\w\W]*\*/)
我可以使用RegexOptions.Multiline的正则表达式完整地匹配行注释(//注释):
(//((?!\*/).)*)(?!\*/)[^\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";
Run Code Online (Sandbox Code Playgroud)
块表达式匹配
/* remove block comments
else
{
return "FIXED";
} // do not remove nested comments */
Run Code Online (Sandbox Code Playgroud)
这很好,但线条表达匹配
// remove whole line comments
// remove partial line comments
Run Code Online (Sandbox Code Playgroud)
和
// do not remove nested comments
Run Code Online (Sandbox Code Playgroud)
此外,如果我在行表达式中没有两次*/positive前瞻,则匹配
// do not remove nested comments *
Run Code Online (Sandbox Code Playgroud)
我真的不想要.
我要的是将匹配字符,从与表达//
,到行的末尾,但不包含*/
之间//
线和结束.
另外,为了满足我的好奇心,任何人都能解释为什么我需要两次前瞻吗? (//((?!\*/).)*)[^\r\n]
并且(//(.)*)(?!\*/)[^\r\n]
都将包括*,但(//((?!\*/).)*)(?!\*/)[^\r\n]
并(//((?!\*/).)*(?!\*/))[^\r\n]
不会.
Tim*_*mwi 80
两个正则表达式(用于块和行注释)都有错误.如果你想我可以描述的错误,但我觉得它可能是更有效率,如果我编写一个新的,尤其是因为我打算写一个匹配A一个.
问题是,每次你有时间/*
和//
和文字字符串"干扰"互相,它始终是首先启动的一个优先.这非常方便,因为这正是正则表达式的工作方式:首先找到第一个匹配.
所以让我们定义一个匹配这四个标记中每个标记的正则表达式:
var blockComments = @"/\*(.*?)\*/";
var lineComments = @"//(.*?)\r?\n";
var strings = @"""((\\[^\n]|[^""\n])*)""";
var verbatimStrings = @"@(""[^""]*"")+";
Run Code Online (Sandbox Code Playgroud)
要回答标题中的问题(条带评论),我们需要:
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);
Run Code Online (Sandbox Code Playgroud)
我在Holystream提供的所有示例以及我能想到的各种其他案例上运行此代码,它就像一个魅力.如果您能提供失败的示例,我很乐意为您调整代码.
在实现此操作之前,您需要首先为它创建测试用例
那里可能有更多的案例.
一旦拥有了所有这些,就可以为每个人创建一个解析规则,或者对其中的一些进行分组.
单独使用正则表达式解决这个问题可能会非常困难且容易出错,难以测试,并且很难由您和其他程序员维护.
您可以使用如下表达式对代码进行标记:
@(?:"[^"]*")+|"(?:[^"\n\\]+|\\.)*"|'(?:[^'\n\\]+|\\.)*'|//.*|/\*(?s:.*?)\*/
Run Code Online (Sandbox Code Playgroud)
它也会匹配一些无效的转义/结构(例如'foo'
),但可能会匹配所有感兴趣的有效标记(除非我忘记了某些内容),因此适用于有效的代码.
在替换中使用它并捕获您想要保留的部件将为您提供所需的结果.即:
static string StripComments(string code)
{
var re = @"(@(?:""[^""]*"")+|""(?:[^""\n\\]+|\\.)*""|'(?:[^'\n\\]+|\\.)*')|//.*|/\*(?s:.*?)\*/";
return Regex.Replace(code, re, "$1");
}
Run Code Online (Sandbox Code Playgroud)
应用示例:
using System;
using System.Text.RegularExpressions;
namespace Regex01
{
class Program
{
static string StripComments(string code)
{
var re = @"(@(?:""[^""]*"")+|""(?:[^""\n\\]+|\\.)*""|'(?:[^'\n\\]+|\\.)*')|//.*|/\*(?s:.*?)\*/";
return Regex.Replace(code, re, "$1");
}
static void Main(string[] args)
{
var input = "hello /* world */ oh \" '\\\" // ha/*i*/\" and // bai";
Console.WriteLine(input);
var noComments = StripComments(input);
Console.WriteLine(noComments);
}
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
hello /* world */ oh " '\" // ha/*i*/" and // bai
hello oh " '\" // ha/*i*/" and
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
38195 次 |
最近记录: |