【问题标题】:Replacing a Regex Match Collection in C#在 C# 中替换正则表达式匹配集合
【发布时间】:2009-12-05 22:19:47
【问题描述】:

我需要在文本中找到以 [ 开头并以 ] 结尾的所有内容,并将其替换为函数返回的值。所以,这是我正在做的一个例子:

    public string ProcessTemplate(string input)
    {
        return Regex.Replace(input, @"\[(.*?)\]", new MatchEvaluator(delegate(Match match)
            {
                return ProcessBlock(match.Result("$1"));
            }));
    }

    public string ProcessBlock(string value)
    {
        return Block.FromString(value).Process();
    }

现在,我的问题是何时需要编辑块。所以我想找到块,编辑它们,然后然后在文本中替换它们。

所以,我创建了一个块列表,并将ProcessTemplate 方法分为两个方法:FindBlocksReplaceBlocks

    public void FindBlocks(string input)
    {
        Input = input;

        foreach (Match match in Regex.Matches(input, @"\[(.*?)\]"))
            Blocks.Add(Block.FromString(match.Result("$1")));
    }

    public string ReplaceBlocks()
    {
        string input = Input;

        foreach (Block block in Blocks)
            input = input.Replace("[" + block.OrginalText + "]", block.Process);

        return input;
    }

    public IList<Block> Blocks
    {
        get;
        set;
    }

    public string Input
    {
        get;
        set;
    }

它可以工作,但问题是它很慢。我用System.Diagnostics.Stopwatch测量了每个部分,发现ReplaceBlocks方法中的String.Replace很慢。

我该如何改进它?

谢谢。

【问题讨论】:

  • 我不明白是什么导致您放弃了第一种方法,这似乎是正确的解决方案。你能详细说明一下吗?
  • 马克说得对:这正是 MatchEvaluator 的用途。另外,如果你想要第一个捕获组的内容,match.Groups[1]match.Result("$1") 效率更高。

标签: c# regex performance replace


【解决方案1】:

用 StringBuilder 替换 ReplaceBlock 中的字符串可能会提高性能,因为每次执行 string.replace 时都必须解除分配字符串并重新分配字符串。字符串生成器不需要这样做。

将 ReplaceBlock 的内容替换为以下内容。

// This will require a reference to System.Text
StringBuilder input =new StringBuilder(Input);
  foreach (Block block in Blocks)
  {
    input = input.Replace("[" + block.OrginalText + "]", block.Process);
  }
  return input.ToString();

我还发现用更快的 for 循环替换 foreach 循环。

【讨论】:

    【解决方案2】:

    我觉得很慢

    在进行分析之前不要进行优化。找出您的代码运行缓慢的原因,然后优化这些部分。

    http://c2.com/cgi/wiki?ProfileBeforeOptimizing

    【讨论】:

    • 太棒了!可能更快的一件事是在您最初匹配每个块时存储每个块的字符偏移量。然后通过 Substring 替换该字符范围,而不是使用 string.Replace - 应该更快。当然,如果您替换的内容与原始内容的长度不同,则必须在每次替换后使用该差异更新偏移量。记账更多,但最终可能会更快。
    • @kevingessner:我试过了:“input = input.Substring(0, block.Position) + block.Process() + input.Substring(block.Position + block.Length);”但它不起作用... block.Position = match.Index 和 block.Length = match.Length。你知道为什么它不起作用吗?
    猜你喜欢
    • 1970-01-01
    • 2012-05-16
    • 2013-12-06
    • 2021-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-19
    • 1970-01-01
    相关资源
    最近更新 更多