Count regex replaces (C#)

前端 未结 3 2011
醉话见心
醉话见心 2020-11-30 10:55

Is there a way to count the number of replacements a Regex.Replace call makes?

E.g. for Regex.Replace(\"aaa\", \"a\", \"b\"); I want to get the number 3

相关标签:
3条回答
  • 2020-11-30 11:40

    Thanks to both Chevex and Guffa. I started looking for a better way to get the results and found that there is a Result method on the Match class that does the substitution. That's the missing piece of the jigsaw. Example code below:

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

    With a file test.txt containing aaa, the command line regexrep test.txt "(?<test>aa?)" ${test}b will set %errorlevel% to 2 and change the text to aabab.

    0 讨论(0)
  • 2020-11-30 11:54

    You can use a MatchEvaluator that runs for each replacement, that way you can count how many times it occurs:

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

    The second case is trickier as you have to produce the same result as the replacement pattern would:

    int cnt = 0;
    string result = Regex.Replace("aaa", "(?<test>aa?)", m => {
      cnt++;
      return m.Groups["test"] + "b";
    });
    
    0 讨论(0)
  • 2020-11-30 11:59

    This should do it.

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

    I am not on my dev computer so I can't do it right now, but I am going to experiment later and see if there is a way to do this with lambda expressions instead of declaring the method IncrementCount() just to increment an int.

    EDIT modified to use a lambda expression instead of declaring another method.

    EDIT2 If you don't know the pattern in advance, you can still get all the groupings (The $ groups you refer to) within the match object as they are included as a GroupCollection. Like so:

         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 讨论(0)
提交回复
热议问题