小编典典

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

sql

问题:

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

我的意思是这些评论:

-- This is a comment

不是那些

/* this is a comment */

因为我已经可以处理星级评论。

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

令人惊讶的是我没有使正则表达式工作。我本来以为星级评论会比较困难,但实际上并非如此。

根据要求,在这里我的代码删除/ ** /-style注释(为了使其忽略SQL-
Style字符串,您必须用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

阅读 452

收藏
2021-04-07

共1个答案

小编典典

我会让你们所有人失望。使用正则表达式无法做到这一点。当然,很容易找到不在字符串中的注释(即使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);

这是做什么的:找到每个注释文字。通过计算当前匹配项和最后一个匹配项之间的引号数量,检查每个注释是否在注释中。如果该数字是偶数,则表示它是注释,因此将其删除(找到行的第一行末尾并删除行之间的内容)。如果是奇数,则在字符串内,找到字符串的末尾并移至该字符串。Rgis代码段基于一个奇怪的SQL技巧:
“ this”是一个有效的字符串
。即使两个引号也不相同。如果您的SQL语言不正确,则应尝试一种完全不同的方法。我将为此编写一个程序如果是这种情况,也是如此,但这是更快,更直接的方法。

2021-04-07