【问题标题】:What C#/.NET 2.0 RegEx.Replace does if nothing needs to be replaced?如果不需要替换任何内容,C#/.NET 2.0 RegEx.Replace 会做什么?
【发布时间】:2010-11-04 17:33:52
【问题描述】:

在调用 RegEx.Replace 来处理大量字符串时,我有点担心性能问题,因为我不知道如果没有匹配项会发生什么。

public static void ReplaceOldWithNew(ref string input)
{
    string pattern = //something here
    input = Regex.Replace(input, pattern, FormatReplacement);
}

private string FormatReplacement(Match m)
{
    return String.Concat("x", formatCount++);
}

我应该这样吗

public static void ReplaceOldWithNew(ref string input)
{
    string pattern = //something here
    if (RegEx.IsMatch(input, pattern))
       input = Regex.Replace(input, pattern, FormatReplacement);
}

这样做的问题是,如果有匹配项,它会搜索输入字符串两次。是否有任何解决方案可以仅搜索一次匹配项并仅在需要时创建新的字符串实例。也许使用 RegEx.Matches 之类的。

谢谢和BR - 马蒂

【问题讨论】:

    标签: c# regex performance c#-2.0


    【解决方案1】:

    如果您使用Reflector 检查Regex.Replace,它最终会在内部执行此操作:

    Match match = regex.Match(input, startat);
    if (!match.Success)
    {
        return input;
    }
    

    换句话说,如果模式不匹配,它将提前退出并返回原始输入。您的Regex.IsMatch 用法正在做双重工作,但这是提前知道是否存在匹配项的唯一方法,因为Regex.Replace 返回一个字符串,但没有指示是否存在匹配项。使用带有循环的MatchMatches 不会让您轻松地重构原始字符串,因为您需要找出匹配索引(使用Match 上的Index 属性)并将其拼凑起来一起来。

    如果您希望大量使用正则表达式,您可以考虑使用RegexOptions.Compiled 选项。用它声明您的 Regex 对象并在整个代码中重用它。您需要对此进行一些研究并对其是否值得进行基准测试(即,对于不需要它的场景来说,到处使用该选项是过度的)。

    【讨论】:

    • 好的,再次感谢艾哈迈德!不幸的是,我现在没有时间进行这种研究。这足以让我知道它会提前返回并且不会创建例如 StringBuilder 并在那里构造原始字符串。
    【解决方案2】:

    简短的回答是,创建一个 Regex 对象,然后在您进行搜索时,您将拥有一个可以调用 replace 的匹配集合。像这样的:

    var regex = new Regex(pattern, RegexOptions.Compiled);
    foreach (var currentMatch in regex.Matches)
    {
        //Do stuff
    }
    

    这样,搜索只进行一次,然后只有在匹配时才可以操作。

    【讨论】:

    • 感谢您的回答。这对我没有多大帮助,因为不知道如何“做事”;)艾哈迈德的回答说这不是世界上最简单的事情......
    猜你喜欢
    • 1970-01-01
    • 2022-10-16
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-03
    相关资源
    最近更新 更多