字符串.替换更多出现的后续字符

本文关键字:字符 替换 字符串 | 更新日期: 2023-09-27 18:27:10

最近我使用了String.Replace方法来确保后来包含在HTML注释中的用户输入得到正确的净化。我需要这个输入供以后使用,所以HttpUtility.HtmlEncode不是一个选择。

我的代码对输入调用String.Replace("--","--")。然而,我意识到Replace函数的行为并不像我预期的那样。例如:

var userData = "----";
return userData.Replace("--", "- -"); // returns "- -- -", I expected "- - - -"

或:

var userData = "---";
return userData.Replace("--", "- -"); // returns "- --", I expected "- - -"

在第二个例子中,您可以看到,这种净化是无用的,恶意用户实际上仍然可以结束评论。

现在我的问题是:

  1. 这是否被认为是String.Replace的预期行为
  2. 我能轻松实现我想要实现的输出吗

注意:我知道还有其他方法可以净化输出(例如,用下划线替换连字符),但我对这种特殊的方式感兴趣(即,后面的短划线之间的空格)。

字符串.替换更多出现的后续字符

这是预期的行为,因为对Replace的调用只对字符串进行一次传递。因此,字符串中"-"的每个实例都被"-"替换,每个实例都相互邻接,例如"-"旁边的"-","-"后面的"--"等等,看起来像这样:"-|-|-"(为了清晰起见,添加了<--垂直线)。

只需第二次运行替换即可清除第一次替换产生的相邻"-"字符:

var result = userData.Replace("--", "- -").Replace("--", "- -"); 

我还想指出,虽然对于小示例来说,这种类型的直接字符串操作是可以的,但如果要将其扩展到更大或更迭代的字符串操作,则需要考虑使用System.Text.StringBuilder。每次修改string(即通过连接、追加或调用Replace)时,都会在内存中创建一个新的字符串,因为字符串是不可变的

以下是如何用StringBuilder 做同样的事情

var sb = new System.Text.StringBuilder(userData);
var result = sb.Replace("--", "- -").Replace("--", "- -").ToString(); 

您是否考虑过使用RegEx?有一种RegEx.Replace()方法,您可以使用适当的RegEx模式处理不同的变化和出现

https://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.replace(v=vs.110).aspx

RegEx.Replace(stringToReplaceAndTest,"/-/g"," -");

此RegEx将全局查找短划线,并将其替换为和空白+短划线。。。但就像我说的,你只需要找到正确的模式。。。HTH

string.Replace执行一次字符串传递。为了达到你的期望,做

while(userData.Contains("--"))
{
     userData = userData.Replace("--", "- -");
}

也许这会很有用:

var userData = "----";
userData = Regex.Replace(userData, @"-{1}", " -").TrimStart();
  1. 字符串。替换只执行一次您想要的操作。(返回一个新字符串,其中当前实例中指定字符串的所有出现都被另一个指定字符串替换。)引用

  2. 我愿意,

    public static class StringExtensions
    {
        public static string ReplaceAllOccurrences(
            this string str,
            string oldValue,
            string newValue)
        {
            var result = str;
            while (result.Contains(oldValue))
            {
                result = result.Replace(oldValue, newValue);
            }
            return result;
        }
    }
    
    [TestClass]
    public class ReplaceAllOccurencesTest
    {
        [TestMethod]
        public void Test()
        {
            var userData = "----";
            var replaced = userData.ReplaceAllOccurrences("--", "- -"); // returns "- -- -", I expected "- - - -"
            Assert.AreEqual(replaced, "- - - -");
            userData = "---";
            replaced = userData.ReplaceAllOccurrences("--", "- -"); // returns "- --", I expected "- - -"
            Assert.AreEqual(replaced, "- - -");
        }
    }