我需要搜索一个字符串,并将所有出现的 %FirstName%
和 %PolicyAmount%
替换为从数据库中提取的值 . 问题是FirstName的大小写有所不同 . 这阻止我使用 String.Replace()
方法 . 我已经看过关于这个主题的网页了
Regex.Replace(strInput, strToken, strReplaceWith, RegexOptions.IgnoreCase);
但是出于某种原因,当我尝试用 $0
替换 %PolicyAmount%
时,替换永远不会发生 . 我认为它与美元符号是正则表达式中的保留字符有关 .
是否有其他方法可以使用,不涉及清理输入以处理正则表达式特殊字符?
15 回答
From MSDN
$ 0 - "Substitutes the last substring matched by group number number (decimal)."
在.NET正则表达式中,组0始终是整个匹配 . 对于文字$,你需要
看起来像
string.Replace
应该有一个带有StringComparison
参数的重载 . 既然没有,你可以尝试这样的事情:有点令人困惑的答案,部分原因是问题的 Headers 实际上比要求的具体问题大得多 . 通读后,我试着总结一下 .
这是一种扩展方法,我认为可以避免这里提到的陷阱,并提供最广泛适用的解决方案 .
所以...
这是an extension method @MarkRobinson
这doesn't try to skip Regex @Helge(如果你想在Regex之外把这样的字符串嗅探,你真的必须逐个字节)
传递@MichaelLiu的excellent test case,
"œ".ReplaceCaseInsensitiveFind("oe", "")
,尽管他的行为可能略有不同 .不幸的是,@HA 's comment that you have to Escape all three isn't correct . 初始值和
newValue
不需要 .Note: 但是,您必须在插入 if they're part of what would appear to be a "captured value" marker 的新值中转义
$
. 因此Regex.Replace里面的三个美元符号.Replace里面的内容 . [原文如此] . 没有它,这样的事情会破坏......"This is HIS fork, hIs spoon, hissssssss knife.".ReplaceCaseInsensitiveFind("his", @"he$0r")
这是错误:
告诉你什么,我知道那些对Regex感到满意的人觉得他们的使用可以避免错误,但我经常仍然偏向字节嗅探字符串(但只有在读完Spolsky on encodings之后)才能确保你得到你想要的东西重要的用例 . 让我想起Crockford的“insecure regular expressions” . 我们经常编写允许我们想要的正则表达式(如果我们很幸运),但无意中允许更多(例如,
$10
在我的newValue正则表达式中是否真的是一个有效的"capture value"字符串,上面?)因为我们通常很容易被忽略复杂 .奇怪的是
$
逃避(并且Regex.Escape
没有像_2892361那样逃避被捕获的值模式,正如我在替换值中所期望的那样)让我疯了一会儿 . 编程很难(c)1842这是一种扩展方法 . 不确定我在哪里找到它 .
似乎最简单的方法就是使用.Net附带的Replace方法,并且自.Net 1.0以来一直存在:
要使用此方法,您必须添加对Microsoft.VisualBasic组件的引用 . 此程序集是.Net运行时的标准部分,它不是额外的下载或标记为过时 .
受cfeduke的回答启发,我创建了这个函数,它使用IndexOf在字符串中查找旧值,然后用新值替换它 . 我在处理数百万行的SSIS脚本中使用了这个,而regex方法比这慢 .
扩展C. Dragon 76的流行答案,将他的代码放入一个超载默认
Replace
方法的扩展 .根据Jeff Reddy的回答,进行了一些优化和验证:
类似于C. Dragon的版本,但是如果你只需要一个替换:
这是执行正则表达式替换的另一个选项,因为似乎没有多少人注意到匹配包含字符串中的位置:
正则表达式方法应该有效 . 然而,您还可以做的是小写数据库中的字符串,小写%变量%,然后从数据库中找到下部字符串中的位置和长度 . 请记住,字符串中的位置不会因为较低的情况而改变 .
然后使用一个反向循环(它更容易,如果你不这样做,你将不得不保持后续点移动到的位置的运行计数)通过位置和长度从数据库中删除%lower cased字符串%variables%并插入替换值 .
(因为每个人都在考虑这个) . 这是我的版本(使用空检查,正确输入和替换转义)**灵感来自互联网和其他版本:
用法:
让我说出我的情况,如果你愿意,你可以把我撕成碎片 .
相对来说,正则表达式不是这个问题的答案 - 太慢和内存饥饿 .
StringBuilder比字符串重整更好 .
由于这将是一个补充
string.Replace
的扩展方法,我认为重要的是匹配它的工作方式 - 因此抛出相同参数问题的异常非常重要,因为如果没有替换则返回原始字符串 .我相信拥有StringComparison参数并不是一个好主意 . 我确实尝试过但是michael-liu最初提到的测试用例显示了一个问题: -
虽然IndexOf将匹配,但源字符串(1)中的匹配长度与oldValue.Length(2)之间存在不匹配 . 当oldValue.Length被添加到当前匹配位置并且我无法找到解决方法时,这表现为在其他一些解决方案中引入IndexOutOfRange . Regex无论如何都无法匹配案例,所以我采用了仅使用
StringComparison.OrdinalIgnoreCase
的实用解决方案来解决问题 .我的代码与其他答案类似,但我的转折是我在找到创建
StringBuilder
的麻烦之前寻找匹配 . 如果没有找到,则避免潜在的大分配 . 然后代码成为do{...}while
而不是while{...}
我已经针对其他Answers进行了一些广泛的测试,这种测试速度更快,使用的内存略少 .