【问题标题】:How to replace string with dynamic value in c#?如何在c#中用动态值替换字符串?
【发布时间】:2017-01-28 01:16:21
【问题描述】:

我有这个代码:

string a = "**MustbeReplaced**asdgasfsff**MustbeReplaced**asdfafasfsa";
//MustbeReplaced should be Replaced1, Replaced2, and so on
a = a.Replace("MustbeReplaced", "Replaced"); 

每次有字符串替换时,我想用一个动态值替换它。例如,上述字符串的输出应该是:

"**Replaced1**asdgasfsff**Replaced2**asdfafasfsa"

我知道String.Replace,但据我所知,它仅用于静态String 替换。

有什么办法吗?

【问题讨论】:

  • IndexOf查找第一个匹配项,替换,从前一个位置开始查找下一个匹配项+替换长度,重复直到IndexOf返回-1
  • 使用键“MustbeReplaced”作为分隔符将字符串分解为字符串数组。然后在数组上运行 for 循环。
  • @Esko 不,我想这是另一种情况。就我而言,我不仅需要替换第一次出现,还需要替换所有出现。

标签: c# .net


【解决方案1】:

想要避免使用正则表达式?想要更多性能?使用此代码。 此代码一次只使用一个 StringBuilder。

    public static string ReplaceWithNumberPrefix(this string source, string oldString, string newString, int numberPrefixStart)
    {
        var oldStringLength = oldString.Length;

        var indexes = new List<int>();
        var p = source.IndexOf(oldString);                    
        if (p >= 0)
            do
            {
                indexes.Add(p);
                p = source.IndexOf(oldString, p + 1);                    
            } while (p >= 0);

        var builder = new System.Text.StringBuilder(source);
        var trailingDifference = 0;
        for (int i = 0; i < indexes.Count; i++)
        {
            var replacement = string.Concat(newString, numberPrefixStart);
            var startIndex = indexes[i] + trailingDifference;
            builder.Replace(oldString, replacement, startIndex, oldStringLength);

            numberPrefixStart++;
            trailingDifference = trailingDifference + replacement.Length - oldStringLength;
        }

        return builder.ToString();
    }

【讨论】:

    【解决方案2】:

    可以这样做:

            string source = "**MustbeReplaced**asdgasfsff**MustbeReplaced**asdfafasfsa";
            int count = 0;
            var result = Regex.Replace(source, "MustbeReplaced", m => "Replaced" + (++count));
    

    【讨论】:

      【解决方案3】:

      使用Regex.Replace(String, MatchEvaluator) 重载。 corresponding MSDN page 包含一个几乎完全符合您要求的示例。

      这是一个更简单的例子:

      var input = "MustBeReplaced A MustBeReplaced B";
      
      int i = 1;
      MatchEvaluator evaluator = (m) => "Replaced " + (i++);
      
      // yields Replaced 1 A Replaced 2 B
      var result = Regex.Replace(input, "MustBeReplaced", evaluator);
      

      【讨论】:

      • @LasseV.Karlsen:哦,当然,谢谢。并为您提及 Escape +1!
      【解决方案4】:

      您可以使用已经显示的正则表达式,也可以使用这种更高效但可读性较差的纯字符串方法方法:

      string a = "**MustbeReplaced**asdgasfsff**MustbeReplaced**asdfafasfsa";
      int matchCount = 0, index = 0;
      while ((index = a.IndexOf("MustbeReplaced", index, StringComparison.Ordinal)) >= 0)
      {
          a = a.Remove(index, "MustbeReplaced".Length).Insert(index, "Replaced" + ++matchCount);
      }
      

      【讨论】:

      • 为什么这样更有效率?
      • @LasseV.Karlsen:因为字符串方法比正则表达式更有效
      • 如果同时使用StringBuilder 岂不是更好?
      • @LasseV.Karlsen:这取决于。我已经用我的正则表达式方法进行了测试,并且差异比我想象的要小。正则表达式需要 400 毫秒,而字符串方法方法在 100000 次调用中需要 292 毫秒。
      • 我的测试结果正好相反。我将字符串加倍 5 次以生成 1824 个字符的起始输入,在我的机器上,正则表达式版本在 5 毫秒内运行,删除/插入循环在 19 秒内运行,迭代 100 次。对于这种基本模式匹配,正则表达式是表驱动的,而 Regex.Replace 方法在内部使用 StringBuilder 来构建结果,所以这并不让我感到惊讶。我认为 GC 正在杀死删除/插入版本。
      【解决方案5】:

      您可以使用Regex 类并提供一个委托,该委托将为每次匹配调用一次。它需要返回字符串来替换匹配的文本。

      您只需声明一个保存计数器的变量:

      string a = "**MustbeReplaced**asdgasfsff**MustbeReplaced**asdfafasfsa";
      int replacementIndex = 0;
      string b = Regex.Replace(a, "MustbeReplaced", match =>
      {
          replacementIndex++;
          return $"Replaced{replacementIndex}";
      });
      

      运行后,b 将包含以下内容:

      **Replaced1**asdgasfsff**Replaced2**asdfafasfsa
      

      警告:由于您现在使用的是Regex 类,请注意Regex 将使用的所有特殊字符来增强模式,从而避免简单的逐字符匹配.如果您要替换包含星号、问号、括号等符号的文本,则需要转义这些符号。

      幸运的是,我们可以简单地要求 Regex 类为我们做这件事:

      string a = "**Mustbe?Replaced**asdgasfsff**Mustbe?Replaced**asdfafasfsa";
      int replacementIndex = 0;
      string b = Regex.Replace(a, Regex.Escape("Mustbe?Replaced"), match =>
      {
          replacementIndex++;
          return $"Replaced{replacementIndex}";
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-12-30
        相关资源
        最近更新 更多