【问题标题】:C# String Replace safelyC# 字符串替换安全
【发布时间】:2017-04-23 12:06:06
【问题描述】:

您对如何安全地替换字符串有任何想法或提示吗?

例子:

string Example = "OK OR LOK";

现在我想将“OK”替换为 true,将“LOK”替换为 false。

Example = Example.Replace("OK", "true");
Example = Example.Replace("LOK", "false");

现在结果是:Example = "true or Ltrue";

结果应该是:Example ="true or false";

我了解这个问题,但我不知道如何解决这个问题。

谢谢

【问题讨论】:

  • 先替换 LOK,再替换 OK,因为 OK 是 LOK 的子集
  • @BugFinder - 出色的观察和审查。
  • 另一种选择是基于正则表达式的替换。
  • 我对替换项的顺序没有影响
  • @WiktorStribiżew:这不是重复的。 OP 不想只替换整个单词,也不想替换子字符串。但更好匹配的字符串优先级更高,应该先替换。

标签: c# string replace


【解决方案1】:

你可以先替换最长的字符串,f.e.用这个方法:

public static string ReplaceSafe(string str, IEnumerable<KeyValuePair<string, string>>  replaceAllOfThis)
{
    foreach (var kv in replaceAllOfThis.OrderByDescending(kv => kv.Key.Length))
    {
        str = str.Replace(kv.Key, kv.Value);
    }
    return str;
}

你的例子:

Example = ReplaceSafe(Example, new[] {new KeyValuePair<string, string>("OK", "true"), new KeyValuePair<string, string>("LOK", "false")});

【讨论】:

  • 太棒了!这段代码也解决了这个问题:string Example = "test OR test 2";
【解决方案2】:
Example = Example.Replace("LOK", "false").Replace("OK", "true");

【讨论】:

    【解决方案3】:

    您可以先查找“LOK”,但这无助于解决不匹配“POKE”和产生“PtrueE”等更普遍的问题。

    以下内容查找单词边界:

    new Regex(@"\bLOK\b").Replace(
      new Regex(@"\bOK\b").Replace("OK OR LOK", "true"),
      "false")
    

    还有一种更灵活的方法是同时寻找单词边界并确定在匹配评估器中正在执行哪个替换:

    new Regex(@"\bLOK|OK\b").Replace("OK OR LoK", m =>
    {
      switch(m.Value)
      {
        case "OK":
          return "true";
        default:
          return "false";
      }
    })
    

    这是最不可能在不同搜索键之间进一步发生冲突的方法。

    【讨论】:

    • 好的工作正常,但如果我想这样做,什么都没有发生:string OK = "OK"; string replace = new Regex(@"\b" + OK + "\b").Replace(Example, "true");
    • 您的第二个"\b" 是退格字符的代码,应该是@"\b""\\b"。此外,如果您正在动态构建,您应该使用@"\b" + Regex.Escape(OK) + @"\b",这样如果您的搜索字符串 (OK) 包含正则表达式中的任何特殊字符,它们将被转义以匹配实际字符。
    【解决方案4】:

    对于此类问题,这可能是一个开销,但这里是一个使用 RegEx 的版本,带有负面的后视:

    string Example = "OK OR LOK";
    // Replace "OK" which is not preceded by any word character
    string res = Regex.Replace(Example, @"(?<!\w)OK", "true");
    string res2 = Regex.Replace(res, @"(?<!\w)LOK", "false");
    
    Console.WriteLine(res);
    Console.WriteLine(res2);
    

    编辑:灵感来自@Jon Hanna。

    如果 OK 或 LOK 应该有 OKE 或 LOCKS 之类的尾部,则为空格 (\s) 或字符串结尾 ($) 的正向查找头可以解决问题:

    string res = Regex.Replace(Example, @"(?<!\w)OK(?=[\s|$])", "true");
    string res2 = Regex.Replace(res, @"(?<!\w)LOK(?=[\s|$])", "false");
    

    【讨论】:

    • “OKE”会发生什么?
    • \b 在这里很有用。它匹配单词字符与非单词字符或字符串的开头和结尾之间的边界,而无需前瞻。
    • @JonHanna AHH 很酷,很高兴知道,谢谢。由于您的答案中已经包含它,因此我不会不必要地复制它:)
    • 是的,我猜你会发现它有用的信息。
    猜你喜欢
    • 2021-11-30
    • 2013-04-01
    • 2010-12-06
    • 2013-05-26
    • 1970-01-01
    • 2021-04-19
    • 2011-10-20
    • 2010-12-06
    相关资源
    最近更新 更多