如何在String.replace中忽略大小写

string sentence = "We know it contains 'camel' word."; // Camel can be in different cases: string s1 = "CAMEL"; string s2 = "CaMEL"; string s3 = "CAMeL"; // ... string s4 = "Camel"; // ... string s5 = "camel"; 

如何用'马'replace'骆驼'尽pipestring.Replace不支持ignoreCase左string?

使用正则expression式:

 var regex = new Regex( "camel", RegexOptions.IgnoreCase ); var newSentence = regex.Replace( sentence, "horse" ); 

当然,这也会匹配骆驼的词语,但是不清楚你是否愿意。

如果您需要完全匹配,则可以使用自定义的MatchEvaluator。

 public static class Evaluators { public static string Wrap( Match m, string original, string format ) { // doesn't match the entire string, otherwise it is a match if (m.Length != original.Length) { // has a preceding letter or digit (ie, not a real match). if (m.Index != 0 && char.IsLetterOrDigit( original[m.Index - 1] )) { return m.Value; } // has a trailing letter or digit (ie, not a real match). if (m.Index + m.Length != original.Length && char.IsLetterOrDigit( original[m.Index + m.Length] )) { return m.Value; } } // it is a match, apply the format return string.Format( format, m.Value ); } } 

与前面的示例一起使用,将匹配包装在一个范围内,如下所示:

 var regex = new Regex( highlightedWord, RegexOptions.IgnoreCase ); foreach (var sentence in sentences) { var evaluator = new MatchEvaluator( match => Evaluators.Wrap( match, sentence, "<span class='red'>{0}</span>" ) ); Console.WriteLine( regex.Replace( sentence, evaluator ) ); } 

为string添加一个扩展方法来实现这个技巧:

用法:

 string yourString = "TEXTTOREPLACE"; yourString.Replace("texttoreplace", "Look, I Got Replaced!", StringComparison.OrdinalIgnoreCase); 

码:

 using System; using System.Collections.Generic; using System.IO; public static class Extensions { public static string Replace(this string source, string oldString, string newString, StringComparison comp) { int index = source.IndexOf(oldString, comp); // Determine if we found a match bool MatchFound = index >= 0; if (MatchFound) { // Remove the old text source = source.Remove(index, oldString.Length); // Add the replacemenet text source = source.Insert(index, newString); } return source; } } 

这里是一个扩展方法,采用StringComparison,使用string.IndexOf:

  [Pure] public static string Replace(this string source, string oldValue, string newValue, StringComparison comparisonType) { if (source.Length == 0 || oldValue.Length == 0) return source; var result = new System.Text.StringBuilder(); int startingPos = 0; int nextMatch; while ((nextMatch = source.IndexOf(oldValue, startingPos, comparisonType)) > -1) { result.Append(source, startingPos, nextMatch - startingPos); result.Append(newValue); startingPos = nextMatch + oldValue.Length; } result.Append(source, startingPos, source.Length - startingPos); return result.ToString(); } 

顺便说一句,这里也是一个类似的Contains方法也采取StringComparison:

  [Pure] public static bool Contains(this string source, string value, StringComparison comparisonType) { return source.IndexOf(value, comparisonType) >= 0; } 

一些testing:

 [TestFixture] public class ExternalTests { private static string[] TestReplace_args = { "ab/B/c/ac", "HELLO World/Hello/Goodbye/Goodbye World", "Hello World/world/there!/Hello there!", "hello WoRlD/world/there!/hello there!", "///", "ab///ab", "/ab/cd/", "a|b|c|d|e|f/|//abcdef", "a|b|c|d|e|f|/|/:/a:b:c:d:e:f:", }; [Test, TestCaseSource("TestReplace_args")] public void TestReplace(string teststring) { var split = teststring.Split("/"); var source = split[0]; var oldValue = split[1]; var newValue = split[2]; var result = split[3]; Assert.That(source.Replace(oldValue, newValue, StringComparison.OrdinalIgnoreCase), Is.EqualTo(result)); } } 

由于其方便的OrdinalIgnoreCase实用OrdinalIgnoreCase

  string sentence = "We know it contains 'camel' word."; string wordToFind = "camel"; string replacementWord = "horse"; int index = sentence.IndexOf(wordToFind , StringComparison.OrdinalIgnoreCase) // Did we match the word regardless of case bool match = index >= 0; // perform the replace on the matched word if(match) { sentence = sentence.Remove(index, wordToFind.Length) sentence = sentence.Insert(index, replacementWord) } 

如果C#String类有一个像Java这样的ignoreCase()方法,那肯定会很好。

这里是我的扩展方法,它结合了汤姆·比奇的和sntbob的recursion性,以及对ksun指出的bug的更清晰的修复。

码:

 public static string Replace(this string source, string oldString, string newString, StringComparison comparison) { int index = source.IndexOf(oldString, comparison); while (index > -1) { source = source.Remove(index, oldString.Length); source = source.Insert(index, newString); index = source.IndexOf(oldString, index + newString.Length, comparison); } return source; } 

用法:

 string source = "banana"; Console.WriteLine(source.Replace("AN", "banana", StringComparison.OrdinalIgnoreCase)); 

结果:

bbananabananaa

而且,如果您仍然希望recursion性质是可选的:

码:

 public static string Replace(this string source, string oldString, string newString, StringComparison comparison, bool recursive = true) { int index = source.IndexOf(oldString, comparison); while (index > -1) { source = source.Remove(index, oldString.Length); source = source.Insert(index, newString); if (!recursive) { return source; } index = source.IndexOf(oldString, index + newString.Length, comparison); } return source; } 

用法:

 string source = "banana"; Console.WriteLine(source.Replace("AN", "banana", StringComparison.OrdinalIgnoreCase, false)); 

结果:

bbananaana

你也可以使用String.IndexOf

http://msdn.microsoft.com/en-us/library/system.string.indexof.aspx

这样做比使用RegExpressions(我憎恨他们,因为他们不直观,容易搞砸,虽然这个简单的.Net函数调用提取实际凌乱的正则expression式,并没有提供太多的空间错误),但这可能不是你的问题; 电脑真的很快这些天,对吧? :)使用StringComparison对象的IndexOf的重载允许您可选地忽略大小写,并且因为IndexOf返回指定位置的第一个匹配项,您必须编写一个循环来处理具有多个匹配项的string。

  public static string CustomReplace(string srcText, string toFind, string toReplace, bool matchCase, bool replace0nce) { StringComparison sc = StringComparison.OrdinalIgnoreCase; if (matchCase) sc = StringComparison.Ordinal; int pos; while ((pos = srcText.IndexOf(toFind, sc)) > -1) { srcText = srcText.Remove(pos, toFind.Length); srcText = srcText.Insert(pos, toReplace); if (replace0nce) break; } return srcText; } 

它可能不如其他一些答案有效,但我有点像sntbob写的CustomReplace函数。

但是,它有一个缺陷。 如果文本replace是recursion的,将导致无限循环。 例如,CustomReplace(“我吃香蕉!”,“an”,“banana”,false,false)会导致无限循环,并且string会继续变大。 例如,在第四次迭代之后,string将是“我吃bbbbbananaanaanaanaanas!”

如果你只想replace“香蕉”中的“an”的两个实例,那么你就不得不采取另一种方法。 我修改了sntbob的代码来解释这种情况。 我承认这更复杂,但它处理recursionreplace。

 public static string CustomReplace(string srcText, string toFind, string toReplace, bool matchCase, bool replaceOnce) { StringComparison sc = StringComparison.OrdinalIgnoreCase; if (matchCase) sc = StringComparison.Ordinal; int pos; int previousProcessedLength = 0; string alreadyProcessedTxt = ""; string remainingToProcessTxt = srcText; while ((pos = remainingToProcessTxt.IndexOf(toFind, sc)) > -1) { previousProcessedLength = alreadyProcessedTxt.Length; //Append processed text up until the end of the found string and perform replacement alreadyProcessedTxt += remainingToProcessTxt.Substring(0, pos + toFind.Length); alreadyProcessedTxt = alreadyProcessedTxt.Remove(previousProcessedLength + pos, toFind.Length); alreadyProcessedTxt = alreadyProcessedTxt.Insert(previousProcessedLength + pos, toReplace); //Remove processed text from remaining remainingToProcessTxt = remainingToProcessTxt.Substring(pos + toFind.Length); if (replaceOnce) break; } return alreadyProcessedTxt + remainingToProcessTxt; } 

这是另一个使用StringComparison和扩展方法的替代方法。

 public static StringBuilder Replace(this StringBuilder original, string oldString, string newString, StringComparison stringComparison) { if ( newString == null || original == null || string.IsNullOrEmpty(oldString)) return original; int pos = original.ToString().IndexOf(oldString, 0, stringComparison); while ( pos >= 0 ) { original.Remove(pos, oldString.Length).Insert(pos, newString); pos = original.ToString().IndexOf(oldString, pos + newString.Length + 1, stringComparison); } return original; }