最近我使用了String.Replace方法来确保用户输入(后来包含在HTML注释中)被正确清理。我需要输入以供以后使用,所以HttpUtility.HtmlEncode不是一个选择。
我的代码所做的是在输入上调用String.Replace(“ - ”,“ - - ”)。但是,我意识到Replace函数没有像我预期的那样运行。例如:
var userData = "----";
return userData.Replace("--", "- -"); // returns "- -- -", I expected "- - - -"
要么:
var userData = "---";
return userData.Replace("--", "- -"); // returns "- --", I expected "- - -"
在第二个示例中,您可以看到,此清理无用,恶意用户实际上仍可以结束注释。
现在我的问题:
注意:我知道还有其他方法可以清理输出(例如,用下划线替换连字符),但我对这种特殊方式感兴趣(即后续破折号之间的空格)。
这是预期的行为,因为你对Replace
的调用仅在字符串上进行一次传递。因此,你的字符串中的每个“ - ”实例都被“ - - ”代替,每个实例都相互邻接,例如, “ - - ”旁边的“ - - ”旁边的“ - - ”等等,看起来像这样:“ - - | - - | - - ”( -
只需再次运行替换以清除第一次替换产生的邻接“ - ”字符:
var result = userData.Replace("--", "- -").Replace("--", "- -");
我还想指出,虽然对于小例子这种类型的直接字符串操作很好,但是如果要将其扩展为更大或更多的迭代字符串操作,您可能需要考虑使用System.Text.StringBuilder
。每次修改string
(即通过连接,追加或调用Replace
)时,都会在内存中创建一个新字符串,因为字符串是不可变的。另一方面,StringBuilder
通过使用可变的字符集来解决这个问题,并且当你调用string
时最后只产生一个ToString
。
以下是你如何使用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();
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, "- - -");
}
}