问题:
任何人都可以给我一个可以从 SQL 语句中删除单行注释的工作正则表达式 (C#/VB.NET) 吗?
我的意思是这些评论:
-- This is a comment
不是那些
/* this is a comment */
因为我已经可以应付星评了。
我做了一个小解析器,当它们在行的开头时,它会删除那些注释,但它们也可以在代码之后的某个地方,或者更糟的是,在 SQL 字符串 'hello --Test --世界”
这些注释也应该被删除(当然除了 SQL 字符串中的注释——如果可能的话)。
令人惊讶的是我没有让正则表达式工作。我本以为明星评论会更难,但实际上并非如此。
根据要求,我的代码删除了/**/风格的注释 (为了让它忽略 SQL 样式的字符串,您必须用唯一标识符替换字符串(我使用 4 个连接),然后应用注释删除,然后应用字符串反向替换。
static string RemoveCstyleComments(string strInput)
{
string strPattern = @"/[*][\w\d\s]+[*]/";
//strPattern = @"/\*.*?\*/"; // Doesn't work
//strPattern = "/\\*.*?\\*/"; // Doesn't work
//strPattern = @"/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/ "; // Doesn't work
//strPattern = @"/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/ "; // Doesn't work
// http://stackoverflow.com/questions/462843/improving-fixing-a-regex-for-c-style-block-comments
strPattern = @"/\*(?>(?:(?>[^*]+)|\*(?!/))*)\*/"; // Works !
string strOutput = System.Text.RegularExpressions.Regex.Replace(strInput, strPattern, string.Empty, System.Text.RegularExpressions.RegexOptions.Multiline);
Console.WriteLine(strOutput);
return strOutput;
} // End Function RemoveCstyleComments
最佳答案
我会让你们所有人失望的。这不能用正则表达式来完成。当然,很容易找到不在字符串中的注释(即使是 OP 也能做到),真正的问题是在字符串中找到注释。 look arounds有点希望了,但这还不够。通过告诉您在一行中有前面的引号并不能保证任何事情。唯一能保证你有所作为的是报价的古怪之处。用正则表达式找不到的东西。因此,只需使用非正则表达式方法即可。
编辑: 这是 C# 代码:
String sql = "--this is a test\r\nselect stuff where substaff like '--this comment should stay' --this should be removed\r\n";
char[] quotes = { '\'', '"'};
int newCommentLiteral, lastCommentLiteral = 0;
while ((newCommentLiteral = sql.IndexOf("--", lastCommentLiteral)) != -1)
{
int countQuotes = sql.Substring(lastCommentLiteral, newCommentLiteral - lastCommentLiteral).Split(quotes).Length - 1;
if (countQuotes % 2 == 0) //this is a comment, since there's an even number of quotes preceding
{
int eol = sql.IndexOf("\r\n") + 2;
if (eol == -1)
eol = sql.Length; //no more newline, meaning end of the string
sql = sql.Remove(newCommentLiteral, eol - newCommentLiteral);
lastCommentLiteral = newCommentLiteral;
}
else //this is within a string, find string ending and moving to it
{
int singleQuote = sql.IndexOf("'", newCommentLiteral);
if (singleQuote == -1)
singleQuote = sql.Length;
int doubleQuote = sql.IndexOf('"', newCommentLiteral);
if (doubleQuote == -1)
doubleQuote = sql.Length;
lastCommentLiteral = Math.Min(singleQuote, doubleQuote) + 1;
//instead of finding the end of the string you could simply do += 2 but the program will become slightly slower
}
}
Console.WriteLine(sql);
这是做什么的:找到每条评论文字。对于每一个,通过计算当前匹配项和最后一个匹配项之间的引号数来检查它是否在评论中。如果这个数字是偶数,那么它是一条评论,因此将其删除(找到行的第一端并删除中间的内容)。如果它是奇数,这是在一个字符串中,找到字符串的末尾并移动到它。 Rgis 片段基于一个奇怪的 SQL 技巧:'this"is a valid string。即使 2 个引号不同。如果您的 SQL 语言不正确,您应该尝试一种完全不同的方法。我如果是这种情况,我也会为此编写一个程序,但这个程序更快更直接。
关于c# - 用于删除单行 SQL 注释的正则表达式 (--),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9842991/