Quel code dois-je utiliser pour convertir un SQL comme l'expression d'une regex à la volée?

StackOverflow https://stackoverflow.com/questions/47052

Question

Je suis à la recherche pour convertir un SQL comme énoncé sur la mouche à l'équivalent regex c'est à dire

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

Quelle est la meilleure approche pour faire cela?

P. S.Je suis à la recherche pour ce faire sur l' .Net Framework, C#).

Était-ce utile?

La solution

La Regex suivante convertit un SQL comme motif dans une expression régulière pattern avec l'aide d'un MatchEvaluator délégué.Il gère correctement le crochet blocs et s'échappe spécial Regex caractères.

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);
    });

Autres conseils

En plus de @Nathan-Baulch de la solution, vous pouvez utiliser le code ci-dessous pour aussi gérer le cas où un personnalisé du caractère d'échappement a été définie à l'aide de la LIKE '!%' ESCAPE '!' la syntaxe.

   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);
    }

À partir de votre exemple ci-dessus, je serais d'attaque comme ça (je parle en termes généraux parce que je ne sais pas C#):

Qu'elles s'effondrent par COMME '...', mettre la ... morceaux dans un tableau.Remplacer sans échappement % signes par .*, souligne par ., et dans ce cas la [C-P]arsen se traduit directement en une regex.

Rejoignez le tableau morceaux ensemble avec un tuyau, et envelopper le résultat entre parenthèses, et la norme regex bits.

Le résultat serait:

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

La chose la plus importante ici est de se méfier de toutes les façons que vous pouvez échapper de données, et dont les caractères génériques traduire pour lesquels les expressions régulières.

% becomes .*
_ becomes .

J'ai trouvé un module Perl appelé Regexp::Les Caractères Génériques.Vous pouvez essayer de le porter ou de tenter Perl.NET.J'ai un sentiment que vous pouvez écrire vous-même trop.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top