代码之家  ›  专栏  ›  技术社区  ›  Bittercoder

我将使用什么代码将类似SQL的表达式动态转换为regex?

  •  7
  • Bittercoder  · 技术社区  · 16 年前

    我希望将一个类似SQL的语句转换为等效的regex,即

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

    最好的方法是什么?

    另外,我希望在.NET框架(C)上实现这一点。

    4 回复  |  直到 7 年前
        1
  •  8
  •   Nathan Baulch    12 年前

    下面的regex在 MatchEvaluator 代表。它正确处理方括号块并转义特殊的regex字符。

    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);
        });
    
        2
  •  3
  •   TheEadie    9 年前

    除了@nathan baulch的解决方案外,您还可以使用下面的代码来处理自定义转义符已使用 LIKE '!%' ESCAPE '!' 语法。

       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);
        }
    
        3
  •  2
  •   Martin    16 年前

    从你上面的例子来看,我会这样攻击它(我一般是这样说的,因为我不知道C):

    把它分开 像…… 分成一组。 更换未更换的 % 符号通过 * ,下划线为.,在本例中, [C-P]阿森 直接翻译成regex。

    用一个管道将数组片段重新连接在一起,并将结果用括号和标准regex位括起来。

    结果是:

    /^(.*this.*|Sm.th|[C-P]arsen)$/
    

    这里最重要的是要注意所有可以转义数据的方法,以及哪些通配符转换为哪些正则表达式。

    % becomes .*
    _ becomes .
    
        4
  •  -1
  •   Eugene Yokota    16 年前

    我发现了一个名为 Regexp::Wildcards . 您可以尝试移植它或尝试perl.net。我觉得你也可以自己写点东西。