我需要搜索一个字符串,%FirstName%
并%PolicyAmount%
用数据库中提取的值替换所有出现的字符串.问题是FirstName的大小写有所不同.这使我无法使用该String.Replace()
方法.我已经看过关于这个主题的网页了
Regex.Replace(strInput, strToken, strReplaceWith, RegexOptions.IgnoreCase);
但是出于某些原因,当我尝试更换%PolicyAmount%
时$0
,更换永远不会发生.我认为它与美元符号是正则表达式中的保留字符有关.
是否有其他方法可以使用,不涉及清理输入以处理正则表达式特殊字符?
似乎string.Replace
应该有一个带StringComparison
参数的重载.既然没有,你可以尝试这样的事情:
public static string ReplaceString(string str, string oldValue, string newValue, StringComparison comparison) { StringBuilder sb = new StringBuilder(); int previousIndex = 0; int index = str.IndexOf(oldValue, comparison); while (index != -1) { sb.Append(str.Substring(previousIndex, index - previousIndex)); sb.Append(newValue); index += oldValue.Length; previousIndex = index; index = str.IndexOf(oldValue, index, comparison); } sb.Append(str.Substring(previousIndex)); return sb.ToString(); }
从MSDN
$ 0 - "替换与组号(十进制)匹配的最后一个子字符串."
在.NET正则表达式中,组0始终是整个匹配.对于文字$,你需要
string value = Regex.Replace("%PolicyAmount%", "%PolicyAmount%", @"$$0", RegexOptions.IgnoreCase);
混乱组答案,部分原因是由于问题的标题实际上是一种多大于被问的具体问题.阅读完之后,我不确定任何答案是否能够吸收所有好东西的一些编辑,所以我想我会尝试总结.
这是一种扩展方法,我认为可以避免这里提到的陷阱,并提供最广泛适用的解决方案.
public static string ReplaceCaseInsensitiveFind(this string str, string findMe, string newValue) { return Regex.Replace(str, Regex.Escape(findMe), Regex.Replace(newValue, "\\$[0-9]+", @"$$$0"), RegexOptions.IgnoreCase); }
所以...
这是@MarkRobinson 的扩展方法
这不会试图跳过Regex @Helge(如果你想在Regex之外的字符串嗅探,你真的必须逐个字节)
通过@MichaelLiu的优秀测试案例,"œ".ReplaceCaseInsensitiveFind("oe", "")
尽管他的行为可能略有不同.
不幸的是,@ HA对你Escape
所有三个人的评论是不正确的.初始值newValue
并不需要.
注意:但是,如果它们是看似"捕获值"标记的一部分,则$
必须在插入的新值中转义s .因此Regex.Replace里面的三个美元符号.Replace里面的内容.[原文如此].没有它,这样的事情会破坏......
"This is HIS fork, hIs spoon, hissssssss knife.".ReplaceCaseInsensitiveFind("his", @"he$0r")
这是错误:
An unhandled exception of type 'System.ArgumentException' occurred in System.dll Additional information: parsing "The\hisr\ is\ he\HISr\ fork,\ he\hIsr\ spoon,\ he\hisrsssssss\ knife\." - Unrecognized escape sequence \h.
告诉你吧,我知道,是舒适的正则表达式的人觉得自己的使用可以避免的错误,但我仍然经常偏字节(只读过之后,但闻弦斯波斯基上的编码),以绝对确保你得到你用于重要用例.让我想起克罗克福德对" 不安全的正则表达 "的看法.我们常常写正则表达式,让我们想要的(如果我们幸运的话),但无意让更多的(例如,是$10
真正有效的"捕捉值"串在我的正则表达式NEWVALUE上面?),因为我们还不够周到.这两种方法都有价值,并且都鼓励不同类型的无意识错误.通常很容易低估复杂性.
奇怪的$
逃避(Regex.Escape
并没有逃脱被捕获的价值模式,就像$0
我在替换价值中所期望的那样)让我疯了一会儿.编程很难(c)1842
似乎最简单的方法就是使用.Net附带的Replace方法,并且自.Net 1.0以来一直存在:
string res = Microsoft.VisualBasic.Strings.Replace(res, "%PolicyAmount%", "$0", Compare: Microsoft.VisualBasic.CompareMethod.Text);
要使用此方法,您必须添加对Microsoft.VisualBasic组件的引用.此程序集是.Net运行时的标准部分,它不是额外的下载或标记为过时.
这是一种扩展方法.不确定我在哪里找到它.
public static class StringExtensions { public static string Replace(this string originalString, string oldValue, string newValue, StringComparison comparisonType) { int startIndex = 0; while (true) { startIndex = originalString.IndexOf(oldValue, startIndex, comparisonType); if (startIndex == -1) break; originalString = originalString.Substring(0, startIndex) + newValue + originalString.Substring(startIndex + oldValue.Length); startIndex += newValue.Length; } return originalString; } }
////// A case insenstive replace function. /// /// The string to examine.(HayStack) /// The value to replace.(Needle) /// The new value to be inserted ///A string public static string CaseInsenstiveReplace(string originalString, string oldValue, string newValue) { Regex regEx = new Regex(oldValue, RegexOptions.IgnoreCase | RegexOptions.Multiline); return regEx.Replace(originalString, newValue); }
受cfeduke的回答启发,我创建了这个函数,它使用IndexOf在字符串中查找旧值,然后用新值替换它.我在处理数百万行的SSIS脚本中使用了这个,而regex方法比这慢.
public static string ReplaceCaseInsensitive(this string str, string oldValue, string newValue) { int prevPos = 0; string retval = str; // find the first occurence of oldValue int pos = retval.IndexOf(oldValue, StringComparison.InvariantCultureIgnoreCase); while (pos > -1) { // remove oldValue from the string retval = retval.Remove(pos, oldValue.Length); // insert newValue in it's place retval = retval.Insert(pos, newValue); // check if oldValue is found further down prevPos = pos + newValue.Length; pos = retval.IndexOf(oldValue, prevPos, StringComparison.InvariantCultureIgnoreCase); } return retval; }
扩展C. Dragon 76的流行答案,将他的代码变成一个超载默认Replace
方法的扩展.
public static class StringExtensions { public static string Replace(this string str, string oldValue, string newValue, StringComparison comparison) { StringBuilder sb = new StringBuilder(); int previousIndex = 0; int index = str.IndexOf(oldValue, comparison); while (index != -1) { sb.Append(str.Substring(previousIndex, index - previousIndex)); sb.Append(newValue); index += oldValue.Length; previousIndex = index; index = str.IndexOf(oldValue, index, comparison); } sb.Append(str.Substring(previousIndex)); return sb.ToString(); } }