2011-06-09 72 views
3

我試圖將匹配全字搜索添加到我的小應用程序。 我希望它能做與Visual Studio一樣的事情。 因此,例如,下面的代碼應該很好地工作:匹配整個單詞(Visual Studio風格)

public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      InitializeComponent(); 

      String input = "[ abc() *abc ]"; 

      Match(input, "abc", 2); 
      Match(input, "abc()", 1); 
      Match(input, "*abc", 1); 
      Match(input, "*abc ", 1);    
     } 

     private void Match(String input, String pattern, int expected) 
     { 
      String escapedPattern = Regex.Escape(pattern); 
      MatchCollection mc = Regex.Matches(input, @"\b" + escapedPattern + @"\b", RegexOptions.IgnoreCase); 
      if (mc.Count != expected) 
      { 
       throw new Exception("match whole word isn't working"); 
      } 
     } 
    } 

搜索「ABC」工作正常,但其他模式返回0的結果。 我認爲\ b不足,但我不確定要使用什麼。

任何幫助,將不勝感激。 謝謝

回答

3

\b元字符的字母數字和非字母數字字符之間的字邊界上一致。以非字母數字字符結尾的字符串最終無法匹配,因爲\b按預期工作。

要執行支持兩種類型的數據的正確整個單詞匹配您需要:前或任何字母數字字符後

  • 使用\b
  • 使用\B(資本B)之前或之後任何非字母數字字符
  • 不使用\B如果模式的第一個或最後一個字符有意爲非字母數字字符,例如最後一個帶尾部空格的字符

基於這些要點,您需要額外的邏輯來檢查傳入的搜索詞,以便將其形成適當的模式。 \B以與\b相反的方式工作。如果你不使用\B那麼你可能會錯誤地結束部分匹配。例如,單詞foo*abc將錯誤地與@"\*abc\b"的模式相匹配。

爲了證明:

string input = "[ abc() *abc foo*abc ]"; 
string[] patterns = 
{ 
    @"\babc\b",  // 3 
    @"\babc\(\)\B", // 1 
    @"\B\*abc\b", // 1, \B prefix ensures whole word match, "foo*abc" not matched 
    @"\*abc\b",  // 2, no \B prefix so it matches "foo*abc" 
    @"\B\*abc "  // 1 
}; 

foreach (var pattern in patterns) 
{ 
    Console.WriteLine("Pattern: " + pattern); 
    var matches = Regex.Matches(input, pattern); 
    Console.WriteLine("Matches found: " + matches.Count); 
    foreach (Match match in matches) 
    { 
     Console.WriteLine(" " + match.Value); 
    } 
    Console.WriteLine(); 
} 
0

\b是一個零寬度斷言,匹配單詞字符和非單詞字符。

字母,數字和下劃線是單詞字符。 *,SPACE和parens是非單詞字符。因此,當您使用\b*abc\b作爲您的模式時,它與您的輸入不符,因爲*是非單詞。同樣,你的模式涉及parens。

要解決此問題,請在輸入(未轉義)模式以非單詞字符開始或結束的情況下,您需要消除\b


public void Run() 
    { 
     String input = "[ abc() *abc ]"; 

     Match(input, @"\babc\b", 2); 
     Match(input, @"\babc\(\)", 1); 
     Match(input, @"\*abc\b", 1); 
     Match(input, @"\*abc\b ", 1); 
    } 

    private void Match(String input, String pattern, int expected) 
    { 
     MatchCollection mc = Regex.Matches(input, pattern, RegexOptions.IgnoreCase); 
     Console.WriteLine((mc.Count == expected)? "PASS ({0}=={1})" : "FAIL ({0}!={1})", 
          mc.Count, expected); 
    } 
2

我認爲這是你在找什麼:

@"(?<!\w)" + escapedPattern + @"(?!\w)" 

\b在之前和「字」字的存在與否來定義的在當前位置之後。你只關心之前的第一個字符和之後的最後一個。

相關問題