【问题标题】:Is there a case insensitive string replace in .Net without using Regex?.Net 中是否存在不区分大小写的字符串替换而不使用正则表达式?
【发布时间】:2011-07-29 19:08:00
【问题描述】:

我最近不得不在 .net 中执行一些字符串替换,并发现自己为此目的开发了一个正则表达式替换函数。让它工作后,我不禁想到.Net中一定有一个内置的不区分大小写的替换操作,我错过了?

当然,当有很多其他字符串操作支持不区分大小写的比较时,例如;

var compareStrings  = String.Compare("a", "b", blIgnoreCase);
var equalStrings    = String.Equals("a", "b", StringComparison.CurrentCultureIgnoreCase);

那么必须有一个内置的等价替换?

【问题讨论】:

  • 看看这里的讨论:stackoverflow.com/questions/244531/…。有一个示例扩展方法可以满足您的需求。
  • @RB:谢谢,这是“扩展”.Net 功能的好方法,但我的问题是关于是否有内置方法。我将使用这个例子来包装我的正则表达式替换,干杯。

标签: .net string replace


【解决方案1】:

在这里的 cmets 中找到一个:http://www.codeproject.com/Messages/1835929/this-one-is-even-faster-and-more-flexible-modified.aspx

static public string Replace(string original, string pattern, string replacement, StringComparison comparisonType)
{
     return Replace(original, pattern, replacement, comparisonType, -1);
}

static public string Replace(string original, string pattern, string replacement, StringComparison comparisonType, int stringBuilderInitialSize)
{
     if (original == null)
     {
         return null;
     }

     if (String.IsNullOrEmpty(pattern))
     {
         return original;
     }


     int posCurrent = 0;
     int lenPattern = pattern.Length;
     int idxNext = original.IndexOf(pattern, comparisonType);
     StringBuilder result = new StringBuilder(stringBuilderInitialSize < 0 ? Math.Min(4096, original.Length) : stringBuilderInitialSize);

     while (idxNext >= 0)
     {
        result.Append(original, posCurrent, idxNext - posCurrent);
        result.Append(replacement);

        posCurrent = idxNext + lenPattern;

        idxNext = original.IndexOf(pattern, posCurrent, comparisonType);
      }

      result.Append(original, posCurrent, original.Length - posCurrent);

      return result.ToString();
}

应该是最快的,但我没有检查。

否则,您应该按照 Simon 的建议进行操作并使用 VisualBasic Replace 函数。这是我经常做的,因为它具有不区分大小写的功能。

string s = "SoftWare";
s = Microsoft.VisualBasic.Strings.Replace(s, "software", "hardware", 1, -1, Constants.vbTextCompare);

您必须添加对 Microsoft.VisualBasic dll 的引用。

【讨论】:

  • 感谢您的全面细分。所以看起来没有内置的 .Net 机制,至少现在滚动我自己的机制并没有那么错。干杯。
  • 注意非序数比较类型:要替换的实际部分实际上可能与oldValue 的长度不同,因为æ 匹配AEß 匹配SS...而且我不知道有一个等效于IndexOf() 的方法会返回实际匹配部分的长度...
  • @BrianScott:VisualBasic 命名空间是 .net 运行时的一部分,它不仅限于 VB。可以从 C#(或 F#)项目中引用它。由于历史原因,它被命名为,但它没有虱子。
【解决方案2】:

这并不理想,但您可以导入Microsoft.VisualBasic 并使用Strings.Replace 来执行此操作。否则我认为这是自己滚动或坚持使用正则表达式的情况。

【讨论】:

    【解决方案3】:

    这是一个扩展方法。不知道在哪里找到的。

    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;
        }
    
    }
    

    【讨论】:

    • 这段代码缺少一些重要的检查(如果 oldValue 为空则无限循环)。
    • 如果 originalString 和 oldValue 都为空,也会发生无限循环。如果 originalString 为空,则没有可替换的内容,因此需要检查 originalString 是否为空。还需要检查空字符串。否则这很好用。我已经翻译成 VB.NET 并作为答案发布。
    • 更不用说返回“originalString”对于代码可读性来说很糟糕......
    • @KyleMit 对不起这个感觉的伙伴。不,originalString 在返回修改后的字符串时不是一个好名字(“代码可读性”)......我建议你好好阅读一下:RC Martin 的 Clean Code
    【解决方案4】:

    .NET Core 2.0+ 更新(2017 年 8 月)

    这在 .NET Core 2.0+ 中原生可用,String.Replace 具有以下重载

    public string Replace (string oldValue, string newValue, StringComparison comparisonType);
    public string Replace (string oldValue, string newValue, bool ignoreCase, System.Globalization.CultureInfo culture);
    

    所以你可以像这样使用:

    "A".Replace("a", "b", StringComparison.CurrentCultureIgnoreCase);
    "A".Replace("a", "b", true, CultureInfo.CurrentCulture);
    

    PS:想看看MS是如何实现的可以browse .NET Core source


    旧版 .NET Framework 4.8- 用于 VB 项目的选项

    Visual Basic 有一个Option Compare 设置,可以设置为BinaryText

    默认情况下,设置为 Text 将使项目中的所有字符串比较不区分大小写。

    因此,正如其他答案所建议的那样,如果您正在拉入Microsoft.VisualBasic.dll,则在调用Strings.Replace 时,如果您没有明确传递CompareMethod,该方法将使用actually defer to the Compare option for your file or project 使用[OptionCompare] 参数属性

    所以以下任何一个都可以工作(top 选项仅在 VB 中可用,但都依赖于 VisualBasic.dll

    Option Compare Text
    
    Replace("A","a","b")
    
    Replace("A","a","b", Compare := CompareMethod.Text)
    

    【讨论】:

      【解决方案5】:

      这是 rboarman's answer above 的 VB.NET 改编版本,对 null 和空字符串进行必要的检查以避免无限循环。

      Public Function Replace(ByVal originalString As String, 
                              ByVal oldValue As String, 
                              ByVal newValue As String, 
                              ByVal comparisonType As StringComparison) As String
          If Not String.IsNullOrEmpty(originalString) AndAlso 
             Not String.IsNullOrEmpty(oldValue) AndAlso 
             newValue IsNot Nothing Then
              Dim startIndex As Int32
      
              Do While True
                  startIndex = originalString.IndexOf(oldValue, startIndex, comparisonType)
                  If startIndex = -1 Then Exit Do
                  originalString = originalString.Substring(0, startIndex) & newValue & 
                                   originalString.Substring(startIndex + oldValue.Length)
                  startIndex += newValue.Length
              Loop
          End If
      
          Return originalString
      End Function
      

      【讨论】:

        【解决方案6】:

        我的 2 美分:

        public static string Replace(this string originalString, string oldValue, string newValue, StringComparison comparisonType)
        {
            if (originalString == null)
                return null;
            if (oldValue == null)
                throw new ArgumentNullException("oldValue");
            if (oldValue == string.Empty)
                return originalString;
            if (newValue == null)
                throw new ArgumentNullException("newValue");
        
            const int indexNotFound = -1;
            int startIndex = 0, index = 0;
            while ((index = originalString.IndexOf(oldValue, startIndex, comparisonType)) != indexNotFound)
            {
                originalString = originalString.Substring(0, index) + newValue + originalString.Substring(index + oldValue.Length);
                startIndex = index + newValue.Length;
            }
        
            return originalString;
        }
        
        
        
        Replace("FOOBAR", "O", "za", StringComparison.OrdinalIgnoreCase);
        // "FzazaBAR"
        
        Replace("", "O", "za", StringComparison.OrdinalIgnoreCase);
        // ""
        
        Replace("FOO", "BAR", "", StringComparison.OrdinalIgnoreCase);
        // "FOO"
        
        Replace("FOO", "F", "", StringComparison.OrdinalIgnoreCase);
        // "OO"
        
        Replace("FOO", "", "BAR", StringComparison.OrdinalIgnoreCase);
        // "FOO"
        

        【讨论】:

          【解决方案7】:

          您可以使用Microsoft.VisualBasic.<em>Strings</em>.<strong>Replace</strong> 并传入Microsoft.VisualBasic.<em>CompareMethod</em>.<strong>Text</strong> 进行不区分大小写的替换,如下所示:

          Dim myString As String = "One Two Three"
          myString = Replace(myString, "two", "TWO", Compare:= CompareMethod.Text)
          

          【讨论】:

            【解决方案8】:

            我知道框架中没有固定实例,但这是另一个扩展方法版本,其语句数量最少(尽管可能不是最快的),只是为了好玩。更多版本的替换函数也发布在http://www.codeproject.com/KB/string/fastestcscaseinsstringrep.aspx和“Is there an alternative to string.Replace that is case-insensitive?”。

            public static string ReplaceIgnoreCase(this string alterableString, string oldValue, string newValue){
                if(alterableString == null) return null;
                for(
                    int i = alterableString.IndexOf(oldValue, System.StringComparison.CurrentCultureIgnoreCase);
                    i > -1;
                    i = alterableString.IndexOf(oldValue, i+newValue.Length, System.StringComparison.CurrentCultureIgnoreCase)
                ) alterableString =
                    alterableString.Substring(0, i)
                    +newValue
                    +alterableString.Substring(i+oldValue.Length)
                ;
                return alterableString;
            }
            

            【讨论】:

              【解决方案9】:

              可能有点跑题了,但是虽然不区分大小写的替换被 standard replace 函数覆盖,因为 (?),这里有一个小函数在子字符串之前和/或之后添加文本而不改变子串的大小写:

                  Public Shared Function StrWrap(Haystack As String, Needle As String, Optional AddBefore As String = "", Optional AddAfter As String = "") As String
                      Dim Index = Haystack.ToLower.IndexOf(Needle.ToLower)
                      If Index < 0 Then Return Haystack
                      Return Haystack.Substring(0, Index) + AddBefore + Haystack.Substring(Index, Needle.Length) + AddAfter + Haystack.Substring(Index + Needle.Length)
                  End Function
              

              用法:StrWrap("Hello World Test", "hello", "Hi, ", " and Ahoi")

              结果:“Hi, Hello and Ahoi World Test”


              标准不区分大小写替换

              Replace("Hello World Test", "hello", "Hi", , Compare:=CompareMethod.Text)

              【讨论】:

                猜你喜欢
                • 2011-04-28
                • 2015-06-29
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2013-08-05
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多