什么是一个很好的模式,通过流程的方法,每个单独的正则表达式匹配是一个、很好、流程、模式

2023-09-06 16:20:54 作者:您的智商余额已不足

我想弄清楚,我跑在一个长字符串正则表达式匹配的模式,每一次它找到一个匹配,它运行一个替换就可以了。问题是,替换将根据匹配的值会有所不同。这一新值将通过这样的方法来确定。例如:

I'm trying to figure out a pattern where I run a regex match on a long string, and each time it finds a match, it runs a replace on it. The thing is, the replace will vary depending on the matched value. This new value will be determined by a method. For example:

var matches = Regex.Match(myString, myPattern);
while(matches.Success){
   Regex.Replace(myString, matches.Value, GetNewValue(matches.Groups[1]));
   matches = matches.NextMatch();
}

这个问题(我认为)是,如果我运行Regex.Replace,所有的比赛指标搞的一团糟所以结果最终出来是错误的。有什么建议?

The problem (i think) is that if I run the Regex.Replace, all of the match indexes get messed up so the result ends up coming out wrong. Any suggestions?

推荐答案

如果您更换每个图案有一个固定的字符串, Regex.replace 这是否适合你。你并不需要循环比赛:

If you replace each pattern with a fixed string, Regex.replace does that for you. You don't need to iterate the matches:

Regex.Replace(myString, myPattern, "replacement");

否则,如果更换取决于匹配的值,使用 MatchEvaluator 委托,作为第三个参数 Regex.Replace 。它接收匹配并返回字符串的实例。返回值是替换字符串。如果你不希望替换一些比赛,只返回 match.Value

Otherwise, if the replacement depends upon the matched value, use the MatchEvaluator delegate, as the 3rd argument to Regex.Replace. It receives an instance of Match and returns string. The return value is the replacement string. If you don't want to replace some matches, simply return match.Value:

string myString = "aa bb aa bb";
string myPattern = @"\w+";
string result = Regex.Replace(myString, myPattern, 
                      match => match.Value == "aa" ? "0" : "1" );
Console.WriteLine(result);
// 0 1 0 1

如果你真的需要循环比赛,手动替换它们,你需要从最后一场比赛开始朝第一的更换,从而使该字符串的索引是不是毁了,为即将到来的比赛。这里有一个例子:

If you really need to iterate the matches and replace them manually, you need to start replacement from the last match towards the first, so that the index of the string is not ruined for the upcoming matches. Here's an example:

var matches = Regex.Matches(myString, myPattern);
var matchesFromEndToStart = matches.Cast<Match>().OrderByDescending(m => m.Index);
var sb = new StringBuilder(myString);
foreach (var match in matchesFromEndToStart)
{
    if (IsGood(match))
    {
        sb.Remove(match.Index, match.Length)
          .Insert(match.Index, GetReplacementFor(match));
    }
}

Console.WriteLine(sb.ToString());

只是要小心,你的比赛不包含嵌套实例。如果是这样,您可能需要删除它们内部另一场比赛中的比赛,或者重新运行正则表达式生成每次更换后,新的比赛。我还是推荐第二种方法,它使用了与会代表。

Just be careful, that your matches do not contain nested instances. If so, you either need to remove matches which are inside another match, or rerun the regex pattern to generate new matches after each replacement. I still recommend the second approach, which uses the delegates.