2011-02-14 96 views
15

有沒有一種方法可以計算Regex.Replace調用產生的替換次數?計數正則表達式替換(C#)

E.g.對於Regex.Replace("aaa", "a", "b");我想得到數字3(結果是"bbb");對於Regex.Replace("aaa", "(?<test>aa?)", "${test}b");我想獲得數字2(結果是"aabab")。

方法,我能想到這樣做:

  1. 使用一個遞增捕獲變量MatchEvaluator,做更換手動
  2. 得到一個MatchCollection和重複它,如果用手工更換,並保持一個計數
  3. 搜索第一,並獲得MatchCollection,得到了計數,然後做一個單獨更換

方法1和2需要$手工解析取代方法3需要正則表達式匹配字符串兩次。有沒有更好的辦法。

+0

這是一個簡單的命令行工具,可以用任何正則表達式搜索調用,並將模式替換爲命令行參數。因此理想的情況是需要一種通用的解決方案,不要提前知道該模式。真的,這是爲了興趣 - 在.Net中做這件事的最好方法是什麼?看起來像手動分析$替換的MatchEvaluator方法是前進的方向,但它有點凌亂:( – 2011-02-14 16:50:42

+0

西蒙,看我的編輯。 – Chev 2011-02-14 16:56:36

回答

13

感謝Chevex和Guffa。我開始尋找更好的方法來獲得結果,並發現在Match類中有一個用於替換的Result方法。這是拼圖的缺失部分。下面的實施例的代碼:

using System.Text.RegularExpressions; 

namespace regexrep 
{ 
    class Program 
    { 
     static int Main(string[] args) 
     { 
      string fileText = System.IO.File.ReadAllText(args[0]); 
      int matchCount = 0; 
      string newText = Regex.Replace(fileText, args[1], 
       (match) => 
       { 
        matchCount++; 
        return match.Result(args[2]); 
       }); 
      System.IO.File.WriteAllText(args[0], newText); 
      return matchCount; 
     } 
    } 
} 

與含文件test.txt AAA,命令行regexrep test.txt "(?<test>aa?)" ${test}b將設置%ERRORLEVEL%至2,並切換到aabab的文本。

3

這應該做到這一點。

 int count = 0; 
    string text = Regex.Replace(text, 
      @"(((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)", //Example expression. This one captures URLs. 
      match => 
      { 
       string replacementValue = String.Format("<a href='{0}'>{0}</a>", match.Value); 
       count++; 
       return replacementValue; 
      }); 

我不是我開發的計算機上,所以我不能現在就做,但我將稍後進行試驗,看看是否有一種方法與lambda表達式要做到這一點,而不是聲明方法IncrementCount()僅用於增加一個int。

EDIT修改爲使用lambda表達式而不是聲明另一個方法。

EDIT2如果您事先不知道該模式,您仍然可以獲取匹配對象中的所有分組(您引用的$組),因爲它們包含在GroupCollection中。像這樣:

 int count = 0; 
    string text = Regex.Replace(text, 
      @"(((http|ftp|https):\/\/|www\.)[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?)", //Example expression. This one captures URLs. 
      match => 
      { 
       string replacementValue = String.Format("<a href='{0}'>{0}</a>", match.Value); 
       count++; 
       foreach (Group g in match.Groups) 
       { 
        g.Value; //Do stuff with g.Value 
       } 
       return replacementValue; 
      }); 
+0

這將工作(謝謝!),但基本上我的方法1。爲了使它適用於通用輸入和輸出,你需要解析替換中的$ {test},所以我們需要更復雜的東西(我指的是「手動解析$替換」)。 – 2011-02-14 16:48:24

+0

匹配對象包含$ groups作爲附加到它們的GroupCollection。如果您事先不知道表達式,並且不知道將包括多少個組,那麼像我的EDIT2一樣循環訪問組合集合。我沒有在答案中對團隊價值做任何事情,但應該很容易讓你看到你的成就。 – Chev 2011-02-14 17:04:10

7

您可以使用,對於每次更換運行MatchEvaluator,這樣你可以指望有多少次它發生:

int cnt = 0; 
string result = Regex.Replace("aaa", "a", m => { 
    cnt++; 
    return "b"; 
}); 

第二種情況是棘手的,你必須產生相同的結果作爲替換模式會:

int cnt = 0; 
string result = Regex.Replace("aaa", "(?<test>aa?)", m => { 
    cnt++; 
    return m.Groups["test"] + "b"; 
});