8

その場でSQLのようなステートメントを同等の正規表現に変換しようとしています。

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

これを行うための最良のアプローチは何ですか?

PS私は.Net Framework(C#)でこれをやろうとしています。

4

4 に答える 4

9

MatchEvaluator次の正規表現は、デリゲートの助けを借りて、SQL のようなパターンを正規表現パターンに変換します。角括弧ブロックを正しく処理し、特殊な正規表現文字をエスケープします。

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);
    }) + "$";
于 2012-11-01T15:23:58.017 に答える
3

LIKE '!%' ESCAPE '!'@ Nathan-Baulchのソリューションに加えて、以下のコードを使用して、構文を使用してカスタムエスケープ文字が定義されている場合も処理できます。

   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);
    }
于 2015-04-24T12:24:47.870 に答える
2

上記の例から、次のように攻撃します(C#を知らないため、一般的な用語で話します):

LIKE '...'で分割し、 ...の断片を配列に入れます。エスケープされていない%記号を.*に、アンダースコアを . に置き換えます。この場合、[CP]arsenは正規表現に直接変換されます。

配列の断片をパイプで結合し、結果を括弧と標準の正規表現ビットで囲みます。

結果は次のようになります。

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

ここで最も重要なことは、データをエスケープするすべての方法と、どのワイルドカードがどの正規表現に変換されるかに注意することです。

% becomes .*
_ becomes .
于 2008-09-05T23:34:46.827 に答える
-1

Regexp::Wildcardsという Perl モジュールを見つけました。移植するか、Perl.NET を試すことができます。あなたも自分で何かを書き留めることができると思います。

于 2008-09-05T23:28:11.057 に答える