2008-09-05 17 views

Trả lời

7

Regex sau chuyển đổi mẫu giống SQL thành mẫu Regex với sự trợ giúp của đại diện MatchEvaluator. Nó xử lý chính xác các khối khung vuông và thoát các ký tự Regex đặc biệt.

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

Tôi đã tìm thấy mô-đun Perl có tên Regexp::Wildcards. Bạn có thể thử cổng hoặc thử Perl.NET. Tôi có một cảm giác bạn có thể viết một cái gì đó lên chính mình quá.

2

Từ ví dụ của bạn ở trên, tôi sẽ tấn công nó như thế này (tôi nói một cách chung chung bởi vì tôi không biết C#):

phá vỡ nó ngoài bởi LIKE '...', đặt . .. miếng thành một mảng. Thay thế chưa được thoát % biển báo bằng . *, gạch dưới., Và trong trường hợp này, [C-P] arsen dịch trực tiếp sang regex.

Tham gia các mảng mảng lại với nhau bằng một đường ống và bọc kết quả trong dấu ngoặc đơn và bit regex chuẩn.

Kết quả sẽ là:

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

Điều quan trọng nhất ở đây là để cảnh giác với tất cả những cách bạn có thể thoát dữ liệu, và đó kí tự đại diện dịch mà biểu thức thông thường.

% becomes .* 
_ becomes . 
+0

Một điều cần lưu ý, là nếu mẫu sql có chứa \, thì bạn muốn thoát khỏi mẫu đó trong regex. Regex.Escape sẽ trợ giúp ở đây – mrwaim

3

Ngoài @ giải pháp Nathan-Baulch của bạn có thể sử dụng mã dưới đây cũng để xử lý các trường hợp một nhân vật tùy chỉnh thoát đã được xác định bằng cách sử dụng cú pháp 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); 
    }