371

문자열의 여러 공백을 C #의 공백 하나로 바꾸려면 어떻게합니까?

예:

1 2 3  4    5

다음과 같습니다 :

1 2 3 4 5


  • 상태 머신이 쉽게 수행 할 수 있지만 공백을 제거하기 위해서만 필요하면 과도한 작업이 될 수 있습니다. - Adrian
  • 중복 질문에서 여러 가지 방법으로 벤치마킹을 추가했습니다.stackoverflow.com/a/37592018/582061. 정규식은 이것을 수행하는 가장 빠른 방법이 아니 었습니다. - Stian Standahl

22 답변


390

RegexOptions options = RegexOptions.None;
Regex regex = new Regex("[ ]{2,}", options);     
tempo = regex.Replace(tempo, " ");


  • @Craig는 IMO만으로 충분할 것입니다. //이 블록은 여러 공백을 하나의 공백으로 대체합니다. :) - paulwhit
  • 정말로, RegEx는 이것에 대해 과잉입니다. - Joel Coehoorn
  • 하지만 이제는 2 가지 문제가 있습니다 .... - seanb
  • @ 조엘 : 동의하지 않을 수 있습니다. 실제로이 방법은 충분히 큰 문자열의 경우보다 효율적이며 한 줄로 처리 할 수 있습니다. 잔인한 부분은 어디에서? - Konrad Rudolph
  • @Oscar Joel의 코드는 모든 문자를 통해 간단한 루프가 아닙니다! 2 차 최악의 경우가있는 숨겨진 중첩 루프입니다. 이와 대조적으로,이 정규 표현식은 선형이며 오직 하나의 문자열 (= Joel의 코드와 비교했을 때 배치 비용이 크게 줄어든다)을 만들고, 엔진은 그것을 최적화 할 수 있습니다. (솔직히. NET 정규식은 이것에 대해서는 충분히 똑똑하지만 이론상이 정규 표현식은 싸게 구현되어 더 이상 재미 있지는 않으며 3 개의 상태, 하나의 전환 및 추가 정보가없는 DFA 만 필요합니다. - Konrad Rudolph

538

나는 다음과 같이 사용한다 :

myString = Regex.Replace(myString, @"\s+", " ");

어떤 종류의 공백 (예 : 탭, 줄 바꿈 등)의 실행을 잡아서 단일 공백으로 대체하기 때문에.


  • 약간의 수정 : Regex.Replace (소스, @ "\ s) \ s +", "$ 1"); 발견 된 첫 번째 공백 유형을 리턴합니다. 따라서 5 개의 탭이 있으면 탭을 반환합니다. 누군가가 이것을 선호하는 경우. - F.B. ten Kate
  • @radistao 당신의 링크는 Javascript string replace를위한 것이지 C #를위한 것이 아닙니다. - Shiva
  • @ Shiva, / \ s \ s + /는 표준 POSIX regex 문이며 고유 한 구문을 사용하여 모든 언어로 변환하거나 사용할 수 있습니다 - radistao
  • @ F.B.tenKate 좋은 옵션. 또 다른 예는 탭 - 스페이스 - 스페이스 - 탭 - 뉴 라인이있는 경우 탭을 리턴합니다. - goodeye
  • @ F.B.tenKate의 해결책은 Regex.Replace (source, @ (\ s) \ 1 +, "$ 1"); 복수를 대체 할 것이다.같은하나의 문자로 연속되는 문자. - François Beaune

38

string xyz = "1   2   3   4   5";
xyz = string.Join( " ", xyz.Split( new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries ));


  • 정규식도 작동합니다. - tvanfosson
  • 이것은 정규 표현식보다 읽기 쉽기 때문에 다른 구문을 배우지 않아도됩니다. - Michael Bahig
  • Regex가 필요 없기 때문에 나는 그것을 좋아한다. - AleX_
  • 큰 문자열의 경우 비효율적입니다. - DarcyThomas
  • 또한 선행 및 후행 공백을 제거합니다. - Matzi

37

나는 매트의 대답이 최고라고 생각하지만, 그것이 옳다고 믿지 않는다. 개행 문자를 대체하려면 다음을 사용해야합니다.

myString = Regex.Replace(myString, @"\s+", " ", RegexOptions.Multiline);


  • RegexOptions.Multiline은 ^ 및 $의 의미를 변경하여 전체 줄 문자 문자열 대신 모든 줄 ($ = \ n)의 시작과 끝을 일치시킵니다. \ s는 [\ f \ n \ r \ t \ v]와 같기 때문에 여러 줄 옵션이 꺼져 있어도 줄 바꿈을 대체해야합니다. - SushiGuy
  • Matt의 대답은 이미이 문제를 다뤘습니다. 나는 ' 30 사람들이 눈을 가리고이 답변을 투표 :) - 123iamking

21

LINQ를 사용하는 또 다른 접근 방식 :

 var list = str.Split(' ').Where(s => !string.IsNullOrWhiteSpace(s));
 str = string.Join(" ", list);


21

모든 것보다 훨씬 간단합니다.

while(str.Contains("  ")) str = str.Replace("  ", " ");


  • 이것은 정규 표현식 " {2,} " 캐릭터 라인에 3 개 이상의 연속열이있는 경우 - Jan Goyvaerts
  • @JanGoyvaerts : 10 개의 공백이있는 경우에도 신속하고 더러운 테스트를 만들면 정규식이 느려집니다. 즉, while 루프의 성능을 완전히 없애기 위해 하나의 거대한 부분 문자열 만 공백으로 채워집니다. 공평성을 위해 RegexOptions.Compiled를 사용했습니다. Regex.Replace보다 느립니다. - Brian
  • RegexOptions.Compiled는 IL에 정규식을 컴파일하는 많은 오버 헤드를 추가합니다. 응용 프로그램에서 정규식을 자주 사용하거나 일치하는 속도가 커지면 컴파일 속도가 느려지도록 문자열이 충분히 길지 않는 한 응용 프로그램을 사용하지 마십시오. - Jan Goyvaerts

14

myString = Regex.Replace(myString, " {2,}", " ");


19

Regex는 간단한 작업으로도 느려질 수 있습니다. 이렇게하면 어떤 방법 으로든 사용할 수있는 확장 메서드가 만들어집니다.string.

    public static class StringExtension
    {
        public static String ReduceWhitespace(this String value)
        {
            var newString = new StringBuilder();
            bool previousIsWhitespace = false;
            for (int i = 0; i < value.Length; i++)
            {
                if (Char.IsWhiteSpace(value[i]))
                {
                    if (previousIsWhitespace)
                    {
                        continue;
                    }

                    previousIsWhitespace = true;
                }
                else
                {
                    previousIsWhitespace = false;
                }

                newString.Append(value[i]);
            }

            return newString.ToString();
        }
    }

그것은 다음과 같이 사용될 것입니다 :

string testValue = "This contains     too          much  whitespace."
testValue = testValue.ReduceWhitespace();
// testValue = "This contains too much whitespace."


8

그들을 좋아하지 않는 사람들을 위해Regex, 여기에 사용하는 방법입니다StringBuilder:

    public static string FilterWhiteSpaces(string input)
    {
        if (input == null)
            return string.Empty;

        StringBuilder stringBuilder = new StringBuilder(input.Length);
        for (int i = 0; i < input.Length; i++)
        {
            char c = input[i];
            if (i == 0 || c != ' ' || (c == ' ' && input[i - 1] != ' '))
                stringBuilder.Append(c);
        }
        return stringBuilder.ToString();
    }

내 테스트에서 정적 컴파일 된 Regex에 비해이 방법은 매우 큰 중소 크기 문자열 세트를 사용하여 평균 16 배 더 빠릅니다. 컴파일되지 않거나 정적이 아닌 Regex와 비교할 때 이것은 훨씬 빨라야합니다.

명심하십시오.아니선행 또는 후행 공백을 제거하고 그러한 공백이 여러 번 발생하는 경우에만 제거하십시오.



8

한 줄 솔루션으로이 작업을 간단하게 수행 할 수 있습니다!

string s = "welcome to  london";
s.Replace(" ", "()").Replace(")(", "").Replace("()", " ");

원하는 경우 다른 대괄호 (또는 다른 문자)를 선택할 수 있습니다.


  • 문자열에 " () "을 지정하지 않아야합니다. 또는 ") ("그 안에 또는."wel()come to london)("된다"wel come to london". 대괄호를 사용하여 시도해 볼 수 있습니다. 그래서 사용하십시오.((((()))))대신에())))))(((((대신에)(. 여전히 작동 할 것입니다. 그래도 문자열에((((()))))또는)))))(((((, 이것은 실패합니다. - nmit026

5

이것은 더 짧은 버전입니다.이 버전은 한 번만 수행하는 경우에만 사용해야합니다.Regex클래스가 호출 될 때마다

temp = new Regex(" {2,}").Replace(temp, " "); 

정규 표현식에 익숙하지 않다면 다음과 같은 간단한 설명을 들으실 수 있습니다 :

그만큼{2,}앞의 문자에 대한 정규식 검색을 수행하고 2와 무제한 사이의 부분 문자열을 찾습니다.

그만큼.Replace(temp, " ")문자열 temp의 모든 일치를 공백으로 바꿉니다.

이것을 여러 번 사용하고 싶다면 컴파일 타임에 정규 표현식을 생성하므로 다음과 같은 좋은 옵션이 있습니다.

Regex singleSpacify = new Regex(" {2,}", RegexOptions.Compiled);
temp = singleSpacify.Replace(temp, " ");


5

Regex, no Linq ...는 선행 및 후행 공백을 제거하고 포함 된 다중 공백 세그먼트를 한 공간으로 축소합니다.

string myString = "   0 1 2  3   4               5  ";
myString = string.Join(" ", myString.Split(new char[] { ' ' }, 
StringSplitOptions.RemoveEmptyEntries));

결과 : "0 1 2 3 4 5"


  • 주의 사항 : 분할을 사용하면 실제로 이해하기 쉽지만 놀랍게도 성능에 부정적인 영향을 줄 수 있습니다. 많은 문자열을 만들 수 있으므로이 방법으로 큰 문자열을 처리하는 경우 메모리 사용량을 관찰해야합니다. - Pac0

4

조엘 (Joel) 당 다른 답변을 통합하고, 제가 가면 조금씩 개선 될 것입니다.

너는 이걸로 할 수있어.Regex.Replace():

string s = Regex.Replace (
    "   1  2    4 5", 
    @"[ ]{2,}", 
    " "
    );

또는String.Split():

static class StringExtensions
{
    public static string Join(this IList<string> value, string separator)
    {
        return string.Join(separator, value.ToArray());
    }
}

//...

string s = "     1  2    4 5".Split (
    " ".ToCharArray(), 
    StringSplitOptions.RemoveEmptyEntries
    ).Join (" ");


2

나는 방금 새로운 것을 썼다.Join나는 그것을 좋아한다. 그래서 나는 다시 대답 할 것이라고 생각했다.

public static string Join<T>(this IEnumerable<T> source, string separator)
{
    return string.Join(separator, source.Select(e => e.ToString()).ToArray());
}

이것에 대한 멋진 점 중 하나는 요소가 ToString ()을 호출하여 문자열이 아닌 컬렉션에서 작동한다는 것입니다. 사용법은 여전히 동일합니다.

//...

string s = "     1  2    4 5".Split (
    " ".ToCharArray(), 
    StringSplitOptions.RemoveEmptyEntries
    ).Join (" ");


  • 확장 메소드를 만드는 이유는 무엇입니까? 스트링을 사용 하는게 어때요. 조인 ()? - Eric Schoonover

2

나는 이것이 꽤 오래되었다는 것을 알고 있지만, 거의 같은 것을 성취하려고 노력하면서 이것을 가로 질렀습니다. RegEx 버디에서이 솔루션을 찾았습니다. 이 패턴은 모든 이중 공간을 단일 공백으로 바꾸고 앞뒤 공백을 잘라냅니다.

pattern: (?m:^ +| +$|( ){2,})
replacement: $1

우리가 빈 공간을 다루고 있기 때문에 읽기가 조금 어렵습니다. 그래서 여기에서 다시 "공백"이 "_"로 대체되었습니다.

pattern: (?m:^_+|_+$|(_){2,})  <-- don't use this, just for illustration.

"(? m :"구조는 "multi-line"옵션을 가능하게합니다.) 일반적으로 패턴 자체에서 할 수있는 모든 옵션을 포함시켜 더 자체적으로 포함합니다.


1

이걸로 공백을 제거 할 수 있습니다.

while word.contains("  ")  //double space
   word = word.Replace("  "," "); //replace double space by single space.
word = word.trim(); //to remove single whitespces from start & end.


  • 네,하지만 두 개의 공백을 하나만 사용하면됩니다. 이것은 X 개의 공백을 도울 수 없다. - MGot90
  • 그 While 루프는 제거 될 모든 이중 공간을 처리합니다. - Learner1947

1

많은 답이 올바른 결과물을 제공하지만 가장 좋은 공연을 원하는 사람들에게는 개선점을 찾았습니다.놀라나의 대답(실적에 가장 적합한 답변)이 약 10 % 나 증가했습니다.

public static string MergeSpaces(this string str)
{

    if (str == null)
    {
        return null;
    }
    else
    {
        StringBuilder stringBuilder = new StringBuilder(str.Length);

        int i = 0;
        foreach (char c in str)
        {
            if (c != ' ' || i == 0 || str[i - 1] != ' ')
                stringBuilder.Append(c);
            i++;
        }
        return stringBuilder.ToString();
    }

}


1

이 방법을 시도해 보라.

private string removeNestedWhitespaces(char[] st)
{
    StringBuilder sb = new StringBuilder();
    int indx = 0, length = st.Length;
    while (indx < length)
    {
        sb.Append(st[indx]);
        indx++;
        while (indx < length && st[indx] == ' ')
            indx++;
        if(sb.Length > 1  && sb[0] != ' ')
            sb.Append(' ');
    }
    return sb.ToString();
}

다음과 같이 사용하십시오.

string test = removeNestedWhitespaces("1 2 3  4    5".toCharArray());


  • 뒤에 오는 공백이 제거됩니다. - The_Black_Smurf
  • 죄송합니다. 코드를 수정했습니다. 이제 예상대로 작동합니다. string : " 1 2 3 4 9 " 결과 문자열 : " 1 2 3 4 9 " - Ahmed Aljaff

0

올드 스쿨 :

string oldText = "   1 2  3   4    5     ";
string newText = oldText
                    .Replace("  ", " " + (char)22 )
                    .Replace( (char)22 + " ", "" )
                    .Replace( (char)22 + "", "" );

Assert.That( newText, Is.EqualTo( " 1 2 3 4 5 " ) );


  • 텍스트에 이미 포함되어 있지 않다고 가정합니다.(char)22 - onedaywhen

0

정규 표현식을 사용하지 않고 :

while (myString.IndexOf("  ", StringComparison.CurrentCulture) != -1)
{
    myString = myString.Replace("  ", " ");
}

짧은 문자열에는 사용할 수 있지만 긴 문자열에는 많은 공백을 사용하여 잘못 수행됩니다.


0

정규식 패턴 사용

    [ ]+    #only space

   var text = Regex.Replace(inputString, @"[ ]+", " ");


0

믹스StringBuilderEnumerable.Aggregate ()문자열의 확장 메서드로 :

using System;
using System.Linq;
using System.Text;

public static class StringExtension
{
    public static string StripSpaces(this string s)
    {
        return s.Aggregate(new StringBuilder(), (acc, c) =>
        {
            if (c != ' ' || acc.Length > 0 && acc[acc.Length-1] != ' ')
                acc.Append(c);

            return acc;
        }).ToString();
    }

    public static void Main()
    {
        Console.WriteLine("\"" + StringExtension.StripSpaces("1   Hello       World  2   ") + "\"");
    }
}

입력:

"1   Hello       World  2   "

산출:

"1 Hello World 2 "

연결된 질문


관련된 질문

최근 질문