正则表达式删除单行SQL注释( - )

Ste*_*ger 2 .net c# regex sql vb.net

题:

任何人都可以给我一个可以从SQL语句中删除单行注释的正则表达式(C#/ VB.NET)吗?

我的意思是这些评论:

-- This is a comment
Run Code Online (Sandbox Code Playgroud)

不是那些

/* this is a comment */
Run Code Online (Sandbox Code Playgroud)

因为我已经可以处理明星评论了.

我有一个小的解析器,当它们在行的开头时删除那些注释,但是它们也可以在代码之后的某个地方或者更坏的情况下,在SQL字符串中'hello --Test -- World' 也应该删除那些注释(除了SQL字符串中的那些注释)当然 - 如果可能的话).

令人惊讶的是我没有使用正则表达式.我会认为明星评论更难,但实际上,他们不是.

根据请求,这里我的代码删除/**/ - 样式注释(为了让它忽略SQL样式字符串,你必须用uniqueidentifier替换字符串(我使用4个标准),然后应用注释删除,然后应用string-backsubstitution.

    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 
Run Code Online (Sandbox Code Playgroud)

Mát*_*ond 6

我会让你们失望的.使用正则表达式无法做到这一点.当然,很容易找到不在字符串中的注释(甚至OP也可以),真正的交易是字符串中的注释.环顾四周有一点希望,但这仍然不够.通过告诉你在一行中有一个先前的引用将不保证任何东西.唯一可以保证你的东西的是引用的奇怪之处.用正则表达式找不到的东西.所以只需简单地使用非正则表达式方法.

编辑: 这是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);
Run Code Online (Sandbox Code Playgroud)

这样做:找到每个评论文字.对于每个,通过计算当前匹配与最后一个匹配之间的引号数来检查它是否在评论中.如果这个数字是偶数,则它是一个注释,因此将其删除(找到行的第一行并删除之间的数字).如果它是奇数,这是在一个字符串中,找到字符串的结尾并移动到它.Rgis片段基于一个奇怪的SQL技巧:'this'是一个有效的字符串.即使这两个引号不同.如果你的SQL语言不正确,你应该尝试一种完全不同的方法.我会写一个程序到那个如果是这样的话,那么这个更快,更直接.