【问题标题】:Replace the last occurrence of a word in a string - C#替换字符串中最后一次出现的单词 - C#
【发布时间】:2013-02-12 05:24:14
【问题描述】:

我有一个问题,我需要替换字符串中最后出现的单词。

情况:我得到一个格式如下的字符串:

string filePath ="F:/jan11/MFrame/Templates/feb11";

然后我像这样替换TnaName

filePath = filePath.Replace(TnaName, ""); // feb11 is TnaName

这可行,但是当TnaName 与我的folder name 相同时,我遇到了问题。发生这种情况时,我最终会得到这样的字符串:

F:/feb11/MFrame/Templates/feb11

现在它已经用feb11 替换了两次出现的TnaName。有没有办法只替换字符串中最后一次出现的单词?

注意:feb11TnaName,它来自另一个进程 - 这不是问题。

【问题讨论】:

  • 您的唯一目标是替换路径的最后一部分吗? (即从/ 开始?)
  • 不,不是最后一部分,只是最后一个 TnaName 路径中还有更多内容,但我只为问题生成样本。谢谢。
  • 这个字符串总是指向某物的路径吗?如果是,请考虑使用 System.IO.Path 类。
  • 是的,字符串总是指向某物的路径。

标签: c# asp.net


【解决方案1】:

这是替换最后一次出现的字符串的函数

public static string ReplaceLastOccurrence(string Source, string Find, string Replace)
{
        int place = Source.LastIndexOf(Find);

        if(place == -1)
           return Source;

        string result = Source.Remove(place, Find.Length).Insert(place, Replace);
        return result;
}
  • Source 是您要对其执行操作的字符串。
  • Find 是您要替换的字符串。
  • Replace 是您要替换它的字符串。

【讨论】:

  • 小心,可能没有匹配项(即Place == -1
  • 轻微拼写错误:“occurance”不正确,但您的方法名称正确(occurrence)。
  • 如果没有找到匹配,返回源可能比空字符串更合乎逻辑。
  • 你应该返回“return Source;”而不是“返回 sting.Empty;”因为如果没有找到 Find 字符串,它的逻辑失败。
  • 在 ( 和字符串 Source 之间添加 this ,如:public static string ReplaceLastOccurance(this string Source... 并且你有一个漂亮的扩展方法,你可以使用它来替换任何字符串的最后一次出现的字符串。
【解决方案2】:

使用string.LastIndexOf() 查找字符串最后一次出现的索引,然后使用子字符串查找您的解决方案。

【讨论】:

    【解决方案3】:

    您必须手动进行替换:

    int i = filePath.LastIndexOf(TnaName);
    if (i >= 0)
        filePath = filePath.Substring(0, i) + filePath.Substring(i + TnaName.Length);
    

    【讨论】:

      【解决方案4】:

      我不明白为什么不能使用 Regex:

      public static string RegexReplace(this string source, string pattern, string replacement)
      {
        return Regex.Replace(source,pattern, replacement);
      }
      
      public static string ReplaceEnd(this string source, string value, string replacement)
      {
        return RegexReplace(source, $"{value}$", replacement);
      }
      
      public static string RemoveEnd(this string source, string value)
      {
        return ReplaceEnd(source, value, string.Empty);
      }
      

      用法:

      string filePath ="F:/feb11/MFrame/Templates/feb11";
      filePath = filePath.RemoveEnd("feb11"); // F:/feb11/MFrame/Templates/
      filePath = filePath.ReplaceEnd("feb11","jan11"); // F:/feb11/MFrame/Templates/jan11
      

      【讨论】:

      • 你应该 Regex.Escape() 值。
      • 你的意思是,return Regex.Replace(Regex.Replace(source),pattern, replacement);?
      • 假设有人调用 ReplaceEnd("(foobar)", ")", "thenewend")。你的函数会抛出,因为 ")$" 是一个无效的正则表达式。这将起作用: return RegexReplace(source, Regex.Escape(value)+"$", replacement);你的 RemoveEnd 也有同样的故事。
      • @jcox,我不知道如何避免双重转义,b/c 每个函数都是公共的,所以我们有多个潜在的调用路径。就我而言,我没有将它用于特殊字符,但我确实明白你的意思。
      • @toddmo 我会让 ReplaceEnd 和 RemoveEnd 直接调用 Regex.Replace。不过有点跑题了;我只是想让人们意识到将用户输入注入正则表达式模式可能很棘手。类似于将输入注入 XML 或 SQL —— 需要一些转义机制。
      【解决方案5】:

      使用一行代码可以更简单地实现该解决方案:

       static string ReplaceLastOccurrence(string str, string toReplace, string replacement)
          {
              return Regex.Replace(str, $@"^(.*){Regex.Escape(toReplace)}(.*?)$", $"$1{Regex.Escape(replacement)}$2");
          }
      

      因此,我们利用了正则表达式星号运算符的贪婪性。函数是这样使用的:

      var s = "F:/feb11/MFrame/Templates/feb11";
      var tnaName = "feb11";
      var r = ReplaceLastOccurrence(s,tnaName, string.Empty);
      

      【讨论】:

      • 如果toReplace 没有为正则表达式正确转义,这将中断
      • 你是对的。我通过转义 toReplace 和替换来解决这个问题。
      【解决方案6】:

      您可以使用来自System.IO 命名空间的Path 类:

      string filePath = "F:/jan11/MFrame/Templates/feb11";
      
      Console.WriteLine(System.IO.Path.GetDirectoryName(filePath));
      

      【讨论】:

        【解决方案7】:

        以下内容不会替换路径/字符串中的TnaName,而是在不包含TnaName 的情况下返回它:

        var lastIndex = filePath.LastIndexOf(TnaName); // get position of TnaName
        
        filePath = filePath.Substring(0, lastIndex); // get path till position of TnaName
        

        【讨论】:

        • 虽然只有代码的答案可能会回答这个问题,但您可以通过为您的代码提供上下文、此代码工作的原因以及一些文档参考以供进一步阅读,从而显着提高您的答案质量.来自How to Answer“简洁是可以接受的,但更全面的解释更好。”
        【解决方案8】:

        以下函数在模式(要替换的单词)最后出现的位置拆分字符串。
        然后它使用替换字符串(在字符串的后半部分)更改模式。
        最后,它再次将两个半字符串连接起来。

        using System.Text.RegularExpressions;
        
        public string ReplaceLastOccurance(string source, string pattern, string replacement)
        {
           int splitStartIndex = source.LastIndexOf(pattern, StringComparison.OrdinalIgnoreCase);
           string firstHalf = source.Substring(0, splitStartIndex);
           string secondHalf = source.Substring(splitStartIndex, source.Length - splitStartIndex);
           secondHalf = Regex.Replace(secondHalf, pattern, replacement, RegexOptions.IgnoreCase);
        
           return firstHalf + secondHalf;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-04-19
          • 2011-07-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-15
          相关资源
          最近更新 更多