用坏字符替换String的错误字符

我只是想知道什么是替换必须随后替换的字符串字符的最简单方法。

例如:

var str = "[Hello World]"; //enclose all occurences of [ and ] with brackets[] str = str.Replace("[","[[]").Replace("]","[]]"); 
  • 期望的结果: [[]Hello World[]]
  • 实际结果: [[[]]Hello World[]]

原因显然是已经修改过的字符串的第二个替换。

那么如何用包含“坏”字符的字符替换所有“坏”字符的出现?


快速测量所有方法表明StringBuilder是最有效的方法。

190kb文件(全部以毫秒为单位)

  regexTime 40.5065 replaceTime 20.8891 stringBuilderTime 6.9776 

7MB文件

  regexTime 1209.3529 replaceTime 403.3985 stringBuilderTime 175.2583 

顺便说一下,来自John的直接StringBuilder方法的速度是Sehe的Aggregate方法的两倍

我做了一个扩展:

 public static String EncloseChars(this string input, char[] charsToEnclose, String leftSide, String rightSide) { if (charsToEnclose == null || leftSide == null || rightSide == null) throw new ArgumentException("Invalid arguments for EncloseChars", charsToEnclose == null ? "charsToEnclose" : leftSide == null ? "leftSide" : "rightSide"); Array.Sort(charsToEnclose); StringBuilder sb = new StringBuilder(); foreach (char c in input) { if (Array.BinarySearch(charsToEnclose, c) > -1) sb.Append(leftSide).Append(c).Append(rightSide); else sb.Append(c); } return sb.ToString(); } "[Hello World]".EncloseChars(new char[]{'[', ']'},"[","]"); 

这是一个非常不酷的方式。 但它的优点是非常接近万无一失,我认为,并且不使用正则表达式(如果您不想使用正则表达式)。

 StringBuilder sb = new StringBuilder(); foreach (char c in str.ToCharArray()) { if (c == '[' || c == ']') { sb.Append('[' + c + ']'); } else { sb.Append(c); } } string result = sb.ToString(); 

关于什么:

 str = str.Replace("[", "$1[$2") .Replace("]", "$1]$2") .Replace("$1", "[") .Replace("$2", "]"); 

这种优雅的正则表达方法怎么样:

 Regex.Replace("[Hello World]", @"[\[\]]", "[$0]"); 

unit testing吗?

 [TestMethod] public void UnitTestThat() { Assert.AreEqual(@"[[]Hello World[]]", Regex.Replace("[Hello World]", @"[\[\]]", "[$0]")); } 

通过测试


编辑@JohnMcGrant

这是一个效率稍低的代码版本,顺便提一下,与上面的正则表达式完全相同:

 string result = input.Aggregate(new StringBuilder(), (a, c) => -1 != "[]".IndexOf(c) ? a.AppendFormat("[{0}]", c) : a.Append(c)).ToString(); 

怎么样:

 char[] replacedChars = str.SelectMany(ch => (ch == '[' ? new char[] {'[', '[', ']'} : (ch == ']' ? new char[] {'[', ']', ']'} : new char[] {ch}))).ToArray(); string replaced = new string(replacedChars); 

请注意,这可以避免多循环问题,但创建的数组至少与输入字符串中的字符一样多,因此在性能方面可能不是最佳的。

  StringBuilder result = new StringBuilder(); foreach (Char singleCharacter in str) { result.Append(singleCharacter.Equals('[') ? "[[]" : singleCharacter.Equals(']') ? "[]]" : singleCharacter.ToString()); } str = result.ToString(); 

我有完全相同的问题,所以我做了一个辅助函数来做到这一点

  protected string ReplaceUsingDictionary(string subject, Dictionary pairs) { StringBuilder sb = new StringBuilder(subject); sb.Replace("{", "{{").Replace("}", "}}"); int i=0; foreach (string key in pairs.Keys.ToArray()) { sb.Replace( key.Replace("{", "{{").Replace("}", "}}"), "{" + i + "}" ); i++; } return string.Format(sb.ToString(), pairs.Values.ToArray()); } // usage Dictionary replacements = new Dictionary(); replacements["["] = "[[]"; replacements["]"] = "[]]"; string mystr = ReplaceWithDictionary("[HelloWorld]", replacements); // returns [[]HelloWorld[]]