Welchen Code würde ich verwenden, um einen SQL-ähnlichen Ausdruck im Handumdrehen in einen regulären Ausdruck umzuwandeln?

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

Frage

Ich möchte eine SQL-ähnliche Anweisung im Handumdrehen in den entsprechenden regulären Ausdruck konvertieren, d. h.

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

Was ist der beste Ansatz hierfür?

P.S.Ich möchte dies auf dem .Net Framework (C#) tun.

War es hilfreich?

Lösung

Der folgende Regex wandelt mithilfe von a ein SQL-ähnliches Muster in ein Regex-Muster um MatchEvaluator delegieren.Es verarbeitet eckige Klammerblöcke korrekt und maskiert spezielle Regex-Zeichen.

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

Andere Tipps

Zusätzlich zur Lösung von @Nathan-Baulch können Sie den folgenden Code verwenden, um auch den Fall zu behandeln, in dem ein benutzerdefiniertes Escape-Zeichen mithilfe von definiert wurde 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);
    }

Ausgehend von Ihrem obigen Beispiel würde ich es folgendermaßen angreifen (ich spreche allgemein, weil ich C# nicht kenne):

Brechen Sie es auseinander WIE '...', lege das ... Stücke in ein Array.Ersetzen Sie nicht entkommen % Zeichen von .*, unterstrichen durch ., und in diesem Fall die [C-P]arsen wird direkt in Regex übersetzt.

Verbinden Sie die Array-Teile wieder mit einer Pipe und schließen Sie das Ergebnis in Klammern und Standard-Regex-Bits ein.

Das Ergebnis wäre:

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

Das Wichtigste hierbei ist, dass Sie auf alle Möglichkeiten achten, Daten zu maskieren und welche Platzhalter in welche regulären Ausdrücke übersetzt werden.

% becomes .*
_ becomes .

Ich habe ein Perl-Modul namens gefunden Regexp::Wildcards.Sie können versuchen, es zu portieren oder Perl.NET auszuprobieren.Ich habe das Gefühl, dass Sie auch selbst etwas aufschreiben können.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top