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

时间:2012-02-13 16:38:12

标签: c# .net string replace

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

例如:

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[]{'[', ']'},"[","]");

6 个答案:

答案 0 :(得分:5)

这是一种非常 uncool 的方法。但它的优势在于我非常接近万无一失,并且不使用正则表达式(如果你不想使用正则表达式)。

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

答案 1 :(得分:4)

怎么样:

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

答案 2 :(得分:3)

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

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

单元测试吗?

[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();

答案 3 :(得分:1)

怎么样:

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

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

答案 4 :(得分:1)

    StringBuilder result = new StringBuilder();

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

    str = result.ToString();

答案 5 :(得分:0)

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

    protected string ReplaceUsingDictionary(string subject, Dictionary<string,string> 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<string, string> replacements = new Dictionary<string, string>();
replacements["["] = "[[]";
replacements["]"] = "[]]";

string mystr = ReplaceWithDictionary("[HelloWorld]", replacements); // returns [[]HelloWorld[]]