programing

String. 무시 대소문자 바꾸기

kakaobank 2023. 4. 27. 22:39
반응형

String. 무시 대소문자 바꾸기

나는 "hello world"라는 끈을 가지고 있습니다.

"world"라는 단어를 "csharp"로 대체해야 합니다.

이 경우 사용:

string.Replace("World", "csharp");

하지만 결과적으로, 저는 끈을 교체하지 않습니다.그 이유는 대소문자를 구분하기 때문입니다.원래 문자열에는 "월드"가 포함되어 있지만 저는 "월드"를 대체하려고 합니다.

문자열에서 이러한 대/소문자 구분을 피할 수 있는 방법이 있습니까?대체 방법?

정규식을 사용하여 대/소문자를 구분하지 않는 교체를 수행할 수 있습니다.

class Program
{
    static void Main()
    {
        string input = "hello WoRlD";
        string result = 
           Regex.Replace(input, "world", "csharp", RegexOptions.IgnoreCase);
        Console.WriteLine(result); // prints "hello csharp"
    }
}
var search = "world";
var replacement = "csharp";
string result = Regex.Replace(
    stringToLookInto,
    Regex.Escape(search), 
    replacement.Replace("$","$$"), 
    RegexOptions.IgnoreCase
);

정규군.Regex 언어 요소를 포함할 수 있는 사용자 입력에 의존하는 경우 이스케이프가 유용합니다.

갱신하다

댓글 덕분에 실제로 대체 문자열에서 벗어날 필요가 없습니다.

다음은 코드를 테스트하는 작은 피들입니다.

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

출력은 다음과 같습니다.

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 }

다른 정규 표현 방식보다 2.5배 빠르고 가장 효과적인 방법:

/// <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();

}

참고: 대/소문자 무시 ==StringComparison.OrdinalIgnoreCase의 변수로서.StringComparison comparisonType모든 값을 대체하는 가장 빠르고 대소문자를 구분하지 않는 방법입니다.


이 방법의 장점:

  • 높은 CPU 및 메모리 효율성,
  • 정규 표현(결국 증명)으로 다른 방법보다 2.5배 빠른 가장 빠른 해결책입니다.
  • 입력 문자열(세트)에서 부품을 제거하는 데 적합합니다.newValue로.null), 이에 최적화되었습니다.
  • 원본과 동일합니다.NET C# string.Replace행동, 동일한 예외;
  • 설명이 잘 되어 있고 이해하기 쉽습니다.
  • 단순화 – 정규식 없음.정규 표현식은 다재다능하기 때문에(심지어 컴파일되기도 합니다.
  • 이 방법은 잘 테스트되었으며 다른 솔루션에 무한 루프와 같은 숨겨진 결함이 없으며, 심지어 높은 평가를 받았습니다.

@AsValeO: Regex 언어 요소와 함께 작동하지 않으므로 범용 방법이 아닙니다.

@마이크 스틸리온:이 코드에 문제가 있습니다.새 텍스트가 이전 텍스트의 상위 집합인 경우 무한 루프가 발생할 수 있습니다.


벤치마크 테스트: 이 솔루션은 @Steve B의 regex보다 2.59배 더 빠릅니다. 코드:

// 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();

오리지널 아이디어 – @Darky711; @MinerR 감사합니다.StringBuilder.

Regex를 사용한 많은 제안.이 확장 방법을 사용하지 않는 것은 어떻습니까?

public static string Replace(this string str, string old, string @new, StringComparison comparison)
{
    @new = @new ?? "";
    if (string.IsNullOrEmpty(str) || string.IsNullOrEmpty(old) || old.Equals(@new, comparison))
        return str;
    int foundAt = 0;
    while ((foundAt = str.IndexOf(old, foundAt, comparison)) != -1)
    {
        str = str.Remove(foundAt, old.Length).Insert(foundAt, @new);
        foundAt += @new.Length;
    }
    return str;
}

확장은 우리의 삶을 더 쉽게 만듭니다.

static public class StringExtensions
{
    static public string ReplaceInsensitive(this string str, string from, string to)
    {
        str = Regex.Replace(str, from, to, RegexOptions.IgnoreCase);
        return str;
    }
}

Microsoft를 사용할 수 있습니다. 도우미 함수를 찾기 위한 VisualBasic 네임스페이스:

Replace(sourceString, "replacethis", "withthis", , , CompareMethod.Text)

.Net Core에는 다음과 같은 메서드가 내장되어 있습니다.Replace(String, String, StringComparison) 박사님, 이제 간단하게 다음과 같이 쓸 수 있습니다."...".Replace("oldValue", "newValue", StringComparison.OrdinalIgnoreCase)

전달된 비교 유형을 사용하고 프레임워크와 일치하도록 수정된 @Darky711의 답변 이름 및 xml 주석을 가능한 가깝게 대체합니다.

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

(편집: '누락 링크' 문제를 알지 못했습니다. 죄송합니다.)

여기서 찍은 사진:

string myString = "find Me and replace ME";
string strReplace = "me";
myString = Regex.Replace(myString, "me", strReplace, RegexOptions.IgnoreCase);

대소문자를 구분하지 않는 문자열이 부족하다는 불만을 제기한 것은 당신이 처음이 아닌 것 같습니다.교체하다.

확장 방법을 작성했습니다.

public static string ReplaceIgnoreCase(this string source, string oldVale, string newVale)
    {
        if (source.IsNullOrEmpty() || oldVale.IsNullOrEmpty())
            return source;

        var stringBuilder = new StringBuilder();
        string result = source;

        int index = result.IndexOf(oldVale, StringComparison.InvariantCultureIgnoreCase);

        while (index >= 0)
        {
            if (index > 0)
                stringBuilder.Append(result.Substring(0, index));

            if (newVale.IsNullOrEmpty().IsNot())
                stringBuilder.Append(newVale);

            stringBuilder.Append(result.Substring(index + oldVale.Length));

            result = stringBuilder.ToString();

            index = result.IndexOf(oldVale, StringComparison.InvariantCultureIgnoreCase);
        }

        return result;
    }

이전 확장 방법에 대해 두 가지 추가 확장 방법을 사용합니다.

    public static bool IsNullOrEmpty(this string value)
    {
        return string.IsNullOrEmpty(value);
    }

    public static bool IsNot(this bool val)
    {
        return val == false;
    }

이것은 작동하지 않습니까?저는 다른 어떤 것도 훨씬 더 빠르고 쉽게 상상할 수 없습니다.

public static class ExtensionMethodsString
{
    public static string Replace(this String thisString, string oldValue, string newValue, StringComparison stringComparison)
    {
        string working = thisString;
        int index = working.IndexOf(oldValue, stringComparison);
        while (index != -1)
        {
            working = working.Remove(index, oldValue.Length);
            working = working.Insert(index, newValue);
            index = index + newValue.Length;
            index = working.IndexOf(oldValue, index, stringComparison);
        }
        return working;
    }
}

검색 문자열에서 Petrucio의 답변을 확장하고 Steve B의 답변에서 제안된 대로 일치하는 그룹을 탈출합니다(그리고 내 취향에 약간의 변화가 있음).

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

다음과 같은 예상 결과를 얻을 수 있습니다.

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

그러나 이스케이프를 수행하지 않으면 다음과 같은 동작을 얻을 수 있습니다. 이 동작은 다음과 같습니다.String.Replace대소문자를 구분하지 않습니다.

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

@Georgy Batalov 솔루션을 사용할 때 다음 예제를 사용할 때 문제가 발생했습니다.

string original = "blah, DC=blah,DC=blih,DC=블로우,DC=com", 문자열이 교체됨 = 원래.무시 케이스(, DC=", ".")를 교체합니다.

다음은 제가 그의 내선 번호를 다시 쓴 방법입니다.

public static string ReplaceIgnoreCase(this string source, string oldVale, 
string newVale)
    {
        if (source.IsNullOrEmpty() || oldVale.IsNullOrEmpty())
            return source;

        var stringBuilder = new StringBuilder();
        string result = source;

        int index = result.IndexOf(oldVale, StringComparison.InvariantCultureIgnoreCase);
        bool initialRun = true;

        while (index >= 0)
        {
            string substr = result.Substring(0, index);
            substr = substr + newVale;
            result = result.Remove(0, index);
            result = result.Remove(0, oldVale.Length);

            stringBuilder.Append(substr);

            index = result.IndexOf(oldVale, StringComparison.InvariantCultureIgnoreCase);
        }

        if (result.Length > 0)
        {
            stringBuilder.Append(result);
        }

        return stringBuilder.ToString();
    }

내 이 방법은 대소문자를 무시할 수 있고 전체 단어만 선택할 수 있습니다.

public static string Replace(this string s, string word, string by, StringComparison stringComparison, bool WholeWord)
{
    s = s + " ";
    int wordSt;
    StringBuilder sb = new StringBuilder();
    while (s.IndexOf(word, stringComparison) > -1)
    {
        wordSt = s.IndexOf(word, stringComparison);
        if (!WholeWord || ((wordSt == 0 || !Char.IsLetterOrDigit(char.Parse(s.Substring(wordSt - 1, 1)))) && !Char.IsLetterOrDigit(char.Parse(s.Substring(wordSt + word.Length, 1)))))
        {
            sb.Append(s.Substring(0, wordSt) + by);
        }
        else
        {
            sb.Append(s.Substring(0, wordSt + word.Length));
        }
        s = s.Substring(wordSt + word.Length);
    }
    sb.Append(s);
    return sb.ToString().Substring(0, sb.Length - 1);
}

다른 방법은 String에서 대소문자 구분을 무시하는 것입니다.StringComparison 옵션을 사용하여 ()를 바꿉니다.현재의 문화 무시 사례

string.Replace("World", "csharp", StringComparison.CurrentCultureIgnoreCase)

String Comparison을 추천합니다.ZZY / Gama Sharma가 제안한 Current Culture Ignore Case 방법이는 LINQ와 함께 사용할 수 있는 또 다른 기법입니다.

List<string> ItemsToRedact = new List<string> { "star", "citizen", "test", "universe"};

string Message = "Just like each sTaR is unique yet mAkes the uniVERSE what it is, the light in you makes you who you are";

List<string> ReplacementList = Message.Split(' ').Where(x => ItemsToRedact.Contains(x.ToLower())).ToList();

foreach (var word in ReplacementList)
{
     Message = Message.Replace(word, "[Redacted] ");
}

Console.WriteLine(Message);

returns: 각각의 [Redacted]가 고유하지만 [Redacted]를 만드는 것처럼, 당신 안의 빛은 당신을 당신 자신으로 만듭니다.

이 코드는 더 증류될 수 있지만 가독성을 위해 분리했습니다.

아래 기능은 문자열 집합에서 (이와 같은) 일치 단어를 모두 제거하는 것입니다.라비칸트 소나레에 의해.

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

사해볼있다습니도수용▁the▁try를 시도할 수 있습니다.Regex학생들

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

테스트를 거쳐 100% 작동된 이 제품을 사용하십시오!

VB.NET의 경우

Dim myString As String
Dim oldValue As String
Dim newValue As String

myString = Form1.TextBox1.Text
oldValue = TextBox1.Text
newValue = TextBox2.Text

Dim working As String = myString
Dim index As Integer = working.IndexOf(oldValue, StringComparison.CurrentCultureIgnoreCase)

While index <> -1
    working = working.Remove(index, oldValue.Length)
    working = working.Insert(index, newValue)
    index = index + newValue.Length
    index = working.IndexOf(oldValue, index, StringComparison.CurrentCultureIgnoreCase)
    Form1.TextBox1.Text = working
End While

C#의 경우

private void Button2_Click(System.Object sender, System.EventArgs e)
{
    string myString;
    string oldValue;
    string newValue;

    myString = Form1.TextBox1.Text;
    oldValue = TextBox1.Text;
    newValue = TextBox2.Text;

    string working = myString;
    int index = working.IndexOf(oldValue, StringComparison.CurrentCultureIgnoreCase);

    while (index != -1)
    {
        working = working.Remove(index, oldValue.Length);
        working = working.Insert(index, newValue);
        index = index + newValue.Length;
        index = working.IndexOf(oldValue, index, StringComparison.CurrentCultureIgnoreCase);
        Form1.TextBox1.Text = working;
    }
}

나는 이것이 더 좋습니다 - "Hello World".아래쪽().대체( "world", "csharp");

언급URL : https://stackoverflow.com/questions/6275980/string-replace-ignoring-case

반응형