Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What code would I use to convert a SQL like expression to a regex on the fly?

I'm looking to convert a SQL like statement on the fly to the equivalent regex i.e.

LIKE '%this%'
LIKE 'Sm_th'
LIKE '[C-P]arsen'

What's the best approach to doing this?

P.S. I'm looking to do this on the .Net Framework (C#).

like image 791
Bittercoder Avatar asked Sep 05 '08 23:09

Bittercoder


People also ask

Does SQL like use RegEx?

We use regular expressions to define specific patterns in T-SQL in a LIKE operator and filter results based on specific conditions. We also call these regular expressions as T-SQL RegEx functions. In this article, we will use the term T-SQL RegEx functions for regular expressions.

Can you use RegEx in SQL Server?

Regular expressions are a concise and flexible notation for finding and replacing patterns of text. A specific set of regular expressions can be used in the Find what field of the SQL Server Management Studio Find and Replace dialog box.

Why RegEx is used in SQL?

REGEXP is the operator used when performing regular expression pattern matches. RLIKE is the synonym. It also supports a number of metacharacters which allow more flexibility and control when performing pattern matching. The backslash is used as an escape character.


2 Answers

The following Regex converts an SQL like pattern into a Regex pattern with the help of a MatchEvaluator delegate. It correctly handles square bracket blocks and escapes special Regex characters.

string regexPattern = "^" + Regex.Replace(
    likePattern,
    @"[%_]|\[[^]]*\]|[^%_[]+",
    match =>
    {
        if (match.Value == "%")
        {
            return ".*";
        }
        if (match.Value == "_")
        {
            return ".";
        }
        if (match.Value.StartsWith("[") && match.Value.EndsWith("]"))
        {
            return match.Value;
        }
        return Regex.Escape(match.Value);
    }) + "$";
like image 181
Nathan Baulch Avatar answered Oct 21 '22 12:10

Nathan Baulch


In addition to @Nathan-Baulch's solution you can use the code below to also handle the case where a custom escape character has been defined using the LIKE '!%' ESCAPE '!' syntax.

   public Regex ConvertSqlLikeToDotNetRegex(string regex, char? likeEscape = null)
   {
        var pattern = string.Format(@"
            {0}[%_]|
            [%_]|
            \[[^]]*\]|
            [^%_[{0}]+
            ", likeEscape);

        var regexPattern = Regex.Replace(
            regex,
            pattern,
            ConvertWildcardsAndEscapedCharacters,
            RegexOptions.IgnorePatternWhitespace);

        regexPattern = "^" + regexPattern + "$";

        return new Regex(regexPattern,
            !m_CaseSensitive ? RegexOptions.IgnoreCase : RegexOptions.None);
    }

    private string ConvertWildcardsAndEscapedCharacters(Match match)
    {
        // Wildcards
        switch (match.Value)
        {
            case "%":
                return ".*";
            case "_":
                return ".";
        }

        // Remove SQL defined escape characters from C# regex
        if (StartsWithEscapeCharacter(match.Value, likeEscape))
        {
            return match.Value.Remove(0, 1);
        }

        // Pass anything contained in []s straight through 
        // (These have the same behaviour in SQL LIKE Regex and C# Regex)
        if (StartsAndEndsWithSquareBrackets(match.Value))
        {
            return match.Value;
        }

        return Regex.Escape(match.Value);
    }

    private static bool StartsAndEndsWithSquareBrackets(string text)
    {
        return text.StartsWith("[", StringComparison.Ordinal) &&
               text.EndsWith("]", StringComparison.Ordinal);
    }

    private bool StartsWithEscapeCharacter(string text, char? likeEscape)
    {
        return (likeEscape != null) &&
               text.StartsWith(likeEscape.ToString(), StringComparison.Ordinal);
    }
like image 24
TheEadie Avatar answered Oct 21 '22 13:10

TheEadie