Count regex reemplaza (C #)

¿Hay alguna manera de contar la cantidad de reemplazos que hace una llamada Regex.Replace?

Por ejemplo, para Regex.Replace("aaa", "a", "b"); Quiero sacar el número 3 (el resultado es "bbb" ); para Regex.Replace("aaa", "(?aa?)", "${test}b"); Quiero sacar el número 2 (el resultado es "aabab" ).

Maneras en que puedo pensar para hacer esto:

  1. Use un MatchEvaluator que incremente una variable capturada, haciendo el reemplazo manualmente
  2. Obtenga MatchCollection e itere, haciendo el reemplazo manualmente y manteniendo un conteo
  3. Busque primero y obtenga MatchCollection, obtenga el conteo de eso, luego haga un reemplazo por separado

Los métodos 1 y 2 requieren un análisis manual de $ reemplazos, el método 3 requiere que la expresión regular coincida dos veces con la cadena. ¿Hay una mejor manera?

Gracias a Chevex y Guffa. Empecé a buscar una forma mejor de obtener los resultados y descubrí que hay un método de resultado en la clase Match que realiza la sustitución. Esa es la pieza faltante del rompecabezas. Ejemplo de código a continuación:

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

Con un archivo test.txt que contiene aaa, la línea de comando regexrep test.txt "(?aa?)" ${test}b establecerá% errorlevel% en 2 y cambiará el texto a aabab.

Puede usar un MatchEvaluator que se ejecuta para cada reemplazo, de esa manera puede contar cuántas veces ocurre:

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

El segundo caso es más complicado ya que debe producir el mismo resultado que el patrón de reemplazo:

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

Esto debería hacerlo.

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

No estoy en mi computadora dev así que no puedo hacerlo ahora, pero voy a experimentar más tarde y ver si hay una manera de hacer esto con expresiones lambda en lugar de declarar el método IncrementCount () solo para incrementar una int .

EDITAR modificado para usar una expresión lambda en lugar de declarar otro método.

EDIT2 Si no conoce el patrón de antemano, aún puede obtener todas las agrupaciones (los $ grupos a los que se refiere) dentro del objeto de coincidencia, ya que se incluyen como GroupCollection. Al igual que:

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