C# 用坏字符替换字符串中的坏字符

C# 用坏字符替换字符串中的坏字符,c#,.net,string,replace,C#,.net,String,Replace,我只是想知道替换随后必须替换的字符串的最简单方法是什么 例如: var str = "[Hello World]"; //enclose all occurences of [ and ] with brackets[] str = str.Replace("[","[[]").Replace("]","[]]"); 所需结果:[[]你好,世界[]] 实际结果:[[]]Hello World[]] 原因显然是对已经修改的字符串的第二次替换 那么,如何用包含“坏”字符的字符替换所有出现的“

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

例如:

var str = "[Hello World]";
//enclose all occurences of [ and ] with brackets[] 
str = str.Replace("[","[[]").Replace("]","[]]");
  • 所需结果:
    [[]你好,世界[]]
  • 实际结果:
    [[]]Hello World[]]
原因显然是对已经修改的字符串的第二次替换

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


通过对所有方法的快速测量,我们发现,这种方法是最有效的方法

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

7MB文件

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

我对它进行了扩展:

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

str=str.Replace(“[”,“$1[$2”)
.替换(“]”,“$1]$2”)
.替换(“$1”和“[”)
.替换(“$2”,“]”);
那么:

char[] replacedChars = str.SelectMany(ch => 
                                     (ch == '[' ? new char[] {'[', '[', ']'} :
                                     (ch == ']' ? new char[] {'[', ']', ']'} : 
                                     new char[] {ch}))).ToArray();
string replaced = new string(replacedChars);
请注意,这避免了多个循环的问题,但至少会创建与输入字符串中的字符数量相同的数组,因此在性能方面可能不是最佳的。

这里有一种非常不酷的方法。但我认为它的优点是非常简单,并且不使用正则表达式(以防您不想使用正则表达式)


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

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

我有完全相同的问题,所以我做了一个助手函数来做这件事

    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[]]
受保护的字符串替换使用字典(字符串主题、字典对)
{
StringBuilder sb=新StringBuilder(主题);
替换(“{”、“{”)。替换(“}”、“}”);
int i=0;
foreach(成对的字符串键.Keys.ToArray())
{
替换(
key.Replace(“{”、“{”).Replace(“}”、“}”),
“{”+i+“}”
);
i++;
}
返回string.Format(sb.ToString(),pairs.Values.ToArray());
}
//用法
字典替换=新字典();
替换[“[”]=“[]”;
替换[“]”]=“[]”;
字符串mystr=ReplaceWithDictionary(“[HelloWorld]”,replacements);//返回[[]HelloWorld[]]

好主意,使用监视器值作为中介。但是您应该检查字符串是否还包含这些监视器值,或者同样的情况再次发生。示例:
Hello[$1]
在替换实际字符值之前,编辑以替换监视器值+实际字符可能会解决Oliver的问题(虽然是以墙和梯子的方式),但我认为这是以牺牲可读性为代价的。可以放心地假设这不会发生,但是,如果括号内的文本可以合法地包含括号,可能会以某种方式漏掉呢。这难道不会打破规则吗?@JohnMGant:不会,因为这意味着需求发生了变化。如果问题不同怎么办?这会打破答案吗?没有。添加了基于@JohnMGant版本的替代方法。我认为正则表达式仍然是最好的方法:)谢谢。通常不酷的方式是最好/最快的。隐藏在扩展方法中时没有问题;)+蒂姆,量得很好。
[TestMethod]
public void UnitTestThat()
{
    Assert.AreEqual(@"[[]Hello World[]]", Regex.Replace("[Hello World]", @"[\[\]]", "[$0]"));
}
string result = input.Aggregate(new StringBuilder(), (a, c) =>
    -1 != "[]".IndexOf(c) ? a.AppendFormat("[{0}]", c) : a.Append(c)).ToString();
    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<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[]]