String.Replace ignoring case

前端 未结 17 642
野趣味
野趣味 2020-11-29 19:03

I have a string called \"hello world\"

I need to replace the word \"world\" to \"csharp\"

for this I use:

string.Replace(\"World\", \"csharp\         


        
相关标签:
17条回答
  • 2020-11-29 19:49

    I prefer this - "Hello World".ToLower().Replace( "world", "csharp" );

    0 讨论(0)
  • 2020-11-29 19:50
    var search = "world";
    var replacement = "csharp";
    string result = Regex.Replace(
        stringToLookInto,
        Regex.Escape(search), 
        replacement.Replace("$","$$"), 
        RegexOptions.IgnoreCase
    );
    

    The Regex.Escape is useful if you rely on user input which can contains Regex language elements

    Update

    Thanks to comments, you actually don't have to escape the replacement string.

    Here is a small fiddle that tests the code:

    using System;
    using System.Text.RegularExpressions;           
    public class Program
    {
        public static void Main()
        {
    
            var tests = new[] {
                new { Input="abcdef", Search="abc", Replacement="xyz", Expected="xyzdef" },
                new { Input="ABCdef", Search="abc", Replacement="xyz", Expected="xyzdef" },
                new { Input="A*BCdef", Search="a*bc", Replacement="xyz", Expected="xyzdef" },
                new { Input="abcdef", Search="abc", Replacement="x*yz", Expected="x*yzdef" },       
                new { Input="abcdef", Search="abc", Replacement="$", Expected="$def" },
            };
    
    
            foreach(var test in tests){
                var result = ReplaceCaseInsensitive(test.Input, test.Search, test.Replacement);
    
                Console.WriteLine(
                    "Success: {0}, Actual: {1}, {2}",
                    result == test.Expected,
                    result,
                    test
                );
    
            }
    
    
        }
    
        private static string ReplaceCaseInsensitive(string input, string search, string replacement){
            string result = Regex.Replace(
                input,
                Regex.Escape(search), 
                replacement.Replace("$","$$"), 
                RegexOptions.IgnoreCase
            );
            return result;
        }
    }
    

    Its output is:

    Success: True, Actual: xyzdef, { Input = abcdef, Search = abc, Replacement = xyz, Expected = xyzdef } 
    Success: True, Actual: xyzdef, { Input = ABCdef, Search = abc, Replacement = xyz, Expected = xyzdef }
    Success: True, Actual: xyzdef, { Input = A*BCdef, Search = a*bc, Replacement = xyz, Expected = xyzdef } 
    Success: True, Actual: x*yzdef, { Input = abcdef, Search = abc, Replacement = x*yz, Expected = x*yzdef} 
    Success: True, Actual: $def, { Input = abcdef, Search = abc, Replacement = $, Expected = $def }
    
    0 讨论(0)
  • 2020-11-29 19:50

    2.5X FASTER and MOST EFFECTIVE method than other's regular expressions methods:

    /// <summary>
    /// Returns a new string in which all occurrences of a specified string in the current instance are replaced with another 
    /// specified string according the type of search to use for the specified string.
    /// </summary>
    /// <param name="str">The string performing the replace method.</param>
    /// <param name="oldValue">The string to be replaced.</param>
    /// <param name="newValue">The string replace all occurrences of <paramref name="oldValue"/>. 
    /// If value is equal to <c>null</c>, than all occurrences of <paramref name="oldValue"/> will be removed from the <paramref name="str"/>.</param>
    /// <param name="comparisonType">One of the enumeration values that specifies the rules for the search.</param>
    /// <returns>A string that is equivalent to the current string except that all instances of <paramref name="oldValue"/> are replaced with <paramref name="newValue"/>. 
    /// If <paramref name="oldValue"/> is not found in the current instance, the method returns the current instance unchanged.</returns>
    [DebuggerStepThrough]
    public static string Replace(this string str,
        string oldValue, string @newValue,
        StringComparison comparisonType)
    {
    
        // Check inputs.
        if (str == null)
        {
            // Same as original .NET C# string.Replace behavior.
            throw new ArgumentNullException(nameof(str));
        }
        if (str.Length == 0)
        {
            // Same as original .NET C# string.Replace behavior.
            return str;
        }
        if (oldValue == null)
        {
            // Same as original .NET C# string.Replace behavior.
            throw new ArgumentNullException(nameof(oldValue));
        }
        if (oldValue.Length == 0)
        {
            // Same as original .NET C# string.Replace behavior.
            throw new ArgumentException("String cannot be of zero length.");
        }
    
    
        //if (oldValue.Equals(newValue, comparisonType))
        //{
        //This condition has no sense
        //It will prevent method from replacesing: "Example", "ExAmPlE", "EXAMPLE" to "example"
        //return str;
        //}
    
    
    
        // Prepare string builder for storing the processed string.
        // Note: StringBuilder has a better performance than String by 30-40%.
        StringBuilder resultStringBuilder = new StringBuilder(str.Length);
    
    
    
        // Analyze the replacement: replace or remove.
        bool isReplacementNullOrEmpty = string.IsNullOrEmpty(@newValue);
    
    
    
        // Replace all values.
        const int valueNotFound = -1;
        int foundAt;
        int startSearchFromIndex = 0;
        while ((foundAt = str.IndexOf(oldValue, startSearchFromIndex, comparisonType)) != valueNotFound)
        {
    
            // Append all characters until the found replacement.
            int @charsUntilReplacment = foundAt - startSearchFromIndex;
            bool isNothingToAppend = @charsUntilReplacment == 0;
            if (!isNothingToAppend)
            {
                resultStringBuilder.Append(str, startSearchFromIndex, @charsUntilReplacment);
            }
    
    
    
            // Process the replacement.
            if (!isReplacementNullOrEmpty)
            {
                resultStringBuilder.Append(@newValue);
            }
    
    
            // Prepare start index for the next search.
            // This needed to prevent infinite loop, otherwise method always start search 
            // from the start of the string. For example: if an oldValue == "EXAMPLE", newValue == "example"
            // and comparisonType == "any ignore case" will conquer to replacing:
            // "EXAMPLE" to "example" to "example" to "example" … infinite loop.
            startSearchFromIndex = foundAt + oldValue.Length;
            if (startSearchFromIndex == str.Length)
            {
                // It is end of the input string: no more space for the next search.
                // The input string ends with a value that has already been replaced. 
                // Therefore, the string builder with the result is complete and no further action is required.
                return resultStringBuilder.ToString();
            }
        }
    
    
        // Append the last part to the result.
        int @charsUntilStringEnd = str.Length - startSearchFromIndex;
        resultStringBuilder.Append(str, startSearchFromIndex, @charsUntilStringEnd);
    
    
        return resultStringBuilder.ToString();
    
    }
    

    Note: ignore case == StringComparison.OrdinalIgnoreCase as parameter for StringComparison comparisonType. It is the fastest, case-insensitive way to replace all values.


    Advantages of this method:

    • High CPU and MEMORY efficiency;
    • It is the fastest solution, 2.5 times faster than other's methods with regular expressions (proof in the end);
    • Suitable for removing parts from the input string (set newValue to null), optimized for this;
    • Same as original .NET C# string.Replace behavior, same exceptions;
    • Well commented, easy to understand;
    • Simpler – no regular expressions. Regular expressions are always slower because of their versatility (even compiled);
    • This method is well tested and there are no hidden flaws like infinite loop in other's solutions, even highly rated:

    @AsValeO: Not works with Regex language elements, so it's not universal method

    @Mike Stillion: There is a problem with this code. If the text in new is a superset of the text in old, this can produce an endless loop.


    Benchmark-proof: this solution is 2.59X times faster than regex from @Steve B., code:

    // Results:
    // 1/2. Regular expression solution: 4486 milliseconds
    // 2/2. Current solution: 1727 milliseconds — 2.59X times FASTER! than regex!
    
    // Notes: the test was started 5 times, the result is an average; release build.
    
    const int benchmarkIterations = 1000000;
    const string sourceString = "aaaaddsdsdsdsdsd";
    const string oldValue = "D";
    const string newValue = "Fod";
    long totalLenght = 0;
    
    Stopwatch regexStopwatch = Stopwatch.StartNew();
    string tempString1;
    for (int i = 0; i < benchmarkIterations; i++)
    {
        tempString1 = sourceString;
        tempString1 = ReplaceCaseInsensitive(tempString1, oldValue, newValue);
    
        totalLenght = totalLenght + tempString1.Length;
    }
    regexStopwatch.Stop();
    
    
    
    Stopwatch currentSolutionStopwatch = Stopwatch.StartNew();
    string tempString2;
    for (int i = 0; i < benchmarkIterations; i++)
    {
        tempString2 = sourceString;
        tempString2 = tempString2.Replace(oldValue, newValue,
            StringComparison.OrdinalIgnoreCase);
    
        totalLenght = totalLenght + tempString2.Length;
    }
    currentSolutionStopwatch.Stop();
    

    Original idea – @Darky711; thanks @MinerR for StringBuilder.

    0 讨论(0)
  • 2020-11-29 19:50

    Below function is to remove all match word like (this) from the string set. By Ravikant Sonare.

    private static void myfun()
    {
        string mystring = "thiTHISThiss This THIS THis tThishiThiss. Box";
        var regex = new Regex("this", RegexOptions.IgnoreCase);
        mystring = regex.Replace(mystring, "");
        string[] str = mystring.Split(' ');
        for (int i = 0; i < str.Length; i++)
        {
            if (regex.IsMatch(str[i].ToString()))
            {
                mystring = mystring.Replace(str[i].ToString(), string.Empty);
    
            }
        }
        Console.WriteLine(mystring);
    }
    
    0 讨论(0)
  • 2020-11-29 19:51

    Modified @Darky711's answer to use the passed in comparison type and match the framework replace naming and xml comments as closely as possible.

    /// <summary>
    /// Returns a new string in which all occurrences of a specified string in the current instance are replaced with another specified string.
    /// </summary>
    /// <param name="str">The string performing the replace method.</param>
    /// <param name="oldValue">The string to be replaced.</param>
    /// <param name="newValue">The string replace all occurrances of oldValue.</param>
    /// <param name="comparisonType">Type of the comparison.</param>
    /// <returns></returns>
    public static string Replace(this string str, string oldValue, string @newValue, StringComparison comparisonType)
    {
        @newValue = @newValue ?? string.Empty;
        if (string.IsNullOrEmpty(str) || string.IsNullOrEmpty(oldValue) || oldValue.Equals(@newValue, comparisonType))
        {
            return str;
        }
        int foundAt;
        while ((foundAt = str.IndexOf(oldValue, 0, comparisonType)) != -1)
        {
            str = str.Remove(foundAt, oldValue.Length).Insert(foundAt, @newValue);
        }
        return str;
    }
    
    0 讨论(0)
  • 2020-11-29 19:53

    Extending Petrucio's answer with Regex.Escape on the search string, and escaping matched group as suggested in Steve B's answer (and some minor changes to my taste):

    public static class StringExtensions
    {
        public static string ReplaceIgnoreCase(this string str, string from, string to)
        {
            return Regex.Replace(str, Regex.Escape(from), to.Replace("$", "$$"), RegexOptions.IgnoreCase);
        }
    }
    

    Which will produce the following expected results:

    Console.WriteLine("(heLLo) wOrld".ReplaceIgnoreCase("(hello) world", "Hi $1 Universe")); // Hi $1 Universe
    Console.WriteLine("heLLo wOrld".ReplaceIgnoreCase("(hello) world", "Hi $1 Universe"));   // heLLo wOrld
    

    However without performing the escapes you would get the following, which is not an expected behaviour from a String.Replace that is just case-insensitive:

    Console.WriteLine("(heLLo) wOrld".ReplaceIgnoreCase_NoEscaping("(hello) world", "Hi $1 Universe")); // (heLLo) wOrld
    Console.WriteLine("heLLo wOrld".ReplaceIgnoreCase_NoEscaping("(hello) world", "Hi $1 Universe"));   // Hi heLLo Universe
    
    0 讨论(0)
提交回复
热议问题