C #에서 여러 공백을 단일 공백으로 바꾸는 방법은 무엇입니까?


440

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

예:

1 2 3  4    5

될 것입니다 :

1 2 3 4 5

1
스테이트 머신은 쉽게 할 수 있지만 공간을 제거하기 위해서만 필요하다면 아마 과잉 일 것입니다
Adrian

중복 질문 stackoverflow.com/a/37592018/582061 에서이를 수행하는 여러 가지 방법에 대한 벤치 마크를 추가했습니다 . 정규식이 가장 빠른 방법은 아닙니다.
Stian Standahl 2016 년

답변:


468
string sentence = "This is a sentence with multiple    spaces";
RegexOptions options = RegexOptions.None;
Regex regex = new Regex("[ ]{2,}", options);     
sentence = regex.Replace(sentence, " ");

2
복사하여 붙여 넣기하면 작동합니다. 나는 정말로 REgex를 좋아하지 않지만 이번에는 내 생명을 구합니다.
Pokus

9
@Craig는 충분할 것입니다, IMO. //이 블록은 여러 공백을 하나로 대체합니다 ... :)
paulwhit

6
실제로 RegEx는 이것으로 과잉입니다.
Joel Coehoorn

11
@Joel : 동의 할 수 없습니다. 실제로이 방법은 충분히 큰 문자열에 대해보다 효율적이며 한 줄로 수행 할 수 있다고 확신합니다. 과잉은 어디에 있습니까?
Konrad Rudolph

24
@Oscar Joel의 코드는 모든 문자를 간단하게 반복하지는 않습니다! 이차 최악의 경우를 갖는 숨겨진 중첩 루프입니다. 대조적으로,이 정규 표현식은 선형이며 단일 문자열 만 생성합니다 (= Joel의 코드와 비교하여 할당 비용을 크게 줄입니다). 또한 엔진이 지옥을 최적화 할 수 있습니다 (솔직히 말하면 .NET 정규식은 의심 스럽습니다. 이것에 대해 충분히 똑똑하지만 이론적 으로이 정규 표현식은 너무 저렴하게 구현되어 더 이상 재밌지 않습니다. 세 개의 상태, 각 전환 및 추가 정보가없는 DFA 만 필요합니다).
Konrad Rudolph

624

나는 사용하고 싶다 :

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

모든 종류의 공백 (예 : 탭, 줄 바꿈 등)을 포착하여 단일 공백으로 바꿉니다.


43
약간 수정 : Regex.Replace (source, @ "(\ s) \ s +", "$ 1"); 처음 발견 된 공백 유형을 반환합니다. 따라서 5 개의 탭이 있으면 탭이 반환됩니다. 누군가가 이것을 선호한다면.
FB ten Kate

@radistao 귀하의 링크는 C #이 아닌 Javascript 문자열 바꾸기 용입니다.
시바

1
@Shiva, / \ s \ s + /는 표준 POSIX 정규식 명령문이며 자체 구문을 사용하여 모든 언어로 변환 / 사용될 수 있습니다
radistao

4
@FBtenKate의 솔루션 정신에서 : Regex.Replace (source, @ "(\ s) \ 1+", "$ 1"); 여러 개의 동일한 연속 문자를 단일 문자로 바꿉니다.
François Beaune

1
선행 및 후행 공백을 제거하려면 다음과 같이 Trim () 함수를 사용해야합니다. var myString = Regex.Replace (myString, @ "\ s +", "") .Trim ();
Harish Nayak

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

6
이것은 정규 표현식보다 더 읽기
쉽습니다.

9
나는 그것이 정규식이 필요하지 않기 때문에 그것을 좋아한다
AleX_

3
큰 문자열에는 비효율적입니다.
DarcyThomas

3
또한 앞뒤 공백도 제거합니다.
Matzi

1
이 답변도 선호합니다. 예전의 멘토는 "문제가 생길 때마다 정규식이 필요하다고 생각하면 두 번 문제가 생겼습니다"<wink>
William Madonna Jr.

38

나는 Matt의 대답이 최고라고 생각하지만 그것이 옳다고 믿지 않습니다. 줄 바꾸기를 바꾸려면 다음을 사용해야합니다.

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

4
RegexOptions.Multiline은 ^와 $의 의미를 변경하여 전체 여러 줄 문자열 대신 모든 줄의 시작과 끝 ($ = \ n)과 일치합니다. \ s는 [\ f \ n \ r \ t \ v]와 같기 때문에 여러 줄 옵션이 꺼져 있어도 줄 바꿈을 바꿔야합니다.
SushiGuy 2016 년

1
매트의 대답은 이미 이것을 다루었습니다. 난 그냥 눈가리개 30 명이 답변 : 업 - 투표 '생각'
123iamking

26

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

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

23

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

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

23
문자열에 3 개 이상의 공백 시퀀스가 ​​포함 된 경우 정규식 "{2,}"보다 훨씬 덜 효율적입니다.
Jan Goyvaerts

2
@ JanGoyvaerts : 10 개의 공백이 있어도 빠르고 더러운 테스트를 할 때 정규 표현식이 느려졌습니다. 즉, while 루프의 성능을 완전히 없애기 위해 공백으로 가득 찬 하나의 거대한 하위 문자열 만 필요합니다. 공정성을 위해 느린 Regex.Replace 대신 RegexOptions.Compiled를 사용했습니다.
Brian

5
RegexOptions.Compiled는 정규식을 IL로 컴파일하는 데 많은 오버 헤드를 추가합니다. 응용 프로그램에서 정규 표현식을 자주 또는 충분히 많이 사용하여 일치 속도를 높이면 컴파일 속도가 저하되지 않는 한 사용하지 마십시오.
Jan Goyvaerts

이것은 매우 비효율적 인 코드의 예입니다. LOL.
pcbabu

1
@pcbabu 많은 경우에 보이는 것만 큼 나쁘지 않습니다. 이 Replace()메소드는 주어진 문자열에서 두 공백의 모든 발생을 처리하므로 문자열에서 쌍을 이루는 공백의 모든 인스턴스에 대해 반복하지 않고 전체 문자열을 다시 할당하지 않습니다. 하나의 새로운 할당이 이들을 모두 처리합니다. 공백이 3 개 이상인 경우에만 루프를 다시 실행하므로 많은 입력 소스에서 드물게 발생합니다. 데이터에 문제가 있음을 보여줄 수 있다면 상태 머신을 작성하여 문자별로 새로운 stringbuilder에 입력하십시오.
Joel Coehoorn

21

간단한 작업으로도 정규식이 느려질 수 있습니다. 이것은 모든에서 사용할 수있는 확장 메소드를 작성합니다 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."


11

를 좋아하지 않는 사람들 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 배 빠릅니다. 컴파일되지 않은 또는 정적이 아닌 정규 표현식과 비교하면 훨씬 빠릅니다.

선행 또는 후행 공백을 제거 하지 않으며 그러한 경우는 여러 번만 발생합니다.


문자가 공백이 아닌 공백인지 확인하려면 아래의 대답을 참조하십시오 .
수확

8

한 줄의 솔루션으로 간단히 할 수 있습니다!

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

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


1
당신은 그것에서 "()" "()"물론 당신의 문자열이없는 만들거나해야한다. 또는 "wel()come to london)("이된다 "wel come to london". 당신은 괄호를 많이 사용하여 시도 할 수 있습니다. 그래서 사용하는 ((((()))))대신에 ()하고 )))))(((((대신 )(. 그것은 것입니다 여전히 작동합니다. 그러나 경우 문자열을 포함 ((((()))))하거나 )))))(((((,이 오류가 발생합니다.
nmit026

7

이 버전은 더 짧은 버전으로, Regex호출 할 때마다 클래스 의 새 인스턴스를 작성하므로 한 번만 수행하는 경우에만 사용해야합니다 .

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

정규 표현식에 익숙하지 않은 경우 간단한 설명은 다음과 같습니다.

{2,}그 앞에 문자의 정규식 검색을 만들고,이 무제한 번 사이의 문자열을 찾습니다.
그만큼.Replace(temp, " ") 공백 문자열 온도에서 모든 일치를 대체합니다.

이것을 여러 번 사용하려면 컴파일 타임에 정규식 IL을 생성하므로 다음과 같은 더 나은 옵션이 있습니다.

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

7

정규식, Linq 없음, 선행 및 후행 공백을 제거하고 내장 된 여러 공백 세그먼트를 하나의 공백으로 줄입니다.

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

결과 : "0 12 34 5"


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

5

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

3

방금 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 (" ");

2
왜 확장 방법을 만드나요? 왜 string.Join ()을 사용하지 않습니까?
Eric Schoonover

3
      // Mysample string
            string str ="hi you           are          a demo";

            //Split the words based on white sapce
            var demo= str .Split(' ').Where(s => !string.IsNullOrWhiteSpace(s));

            //Join the values back and add a single space in between
                    str = string.Join(" ", demo);

//output: string str ="hi you are a demo";

2

나는 이것이 꽤 오래되었다는 것을 알고 있지만 거의 같은 것을 성취하려고 노력하면서 이것을 가로 질러 달렸다. RegEx Buddy에서이 솔루션을 찾았습니다. 이 패턴은 모든 이중 공간을 단일 공간으로 대체하고 선행 및 후행 공간을 자릅니다.

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

빈 공간을 다루기 때문에 읽기가 약간 어렵 기 때문에 여기서 "공백"이 "_"로 대체되었습니다.

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

"(? m :"구문은 "멀티 라인"옵션을 가능하게합니다. 일반적으로 패턴 자체에 포함 할 수있는 모든 옵션을 포함하여 더 독립적입니다.


2

많은 답변이 올바른 결과를 제공하지만 최고의 성능을 찾는 사람들을 위해 Nolanar의 답변 (성능에 가장 적합한 답변)을 약 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

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

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

1
While 루프는 제거 할 모든 이중 공간을 처리합니다.
Learner1947

1

정규식 패턴을 사용하십시오.

    [ ]+    #only space

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

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

실수로 죄송합니다, 코드를 수정했습니다. 이제 예상 테스트 문자열로 작동합니다 : "1 2 3 4 9"결과 문자열 : "1 2 3 4 9"
Ahmed Aljaff

1

여기 약간의 수정이 있습니다Nolonar 원래 대답은 .

문자가 공백이 아닌 공백인지 확인하려면 다음을 사용하십시오.

여러 공백 문자를 단일 공백으로 바꿉니다.

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

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

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

0

정규식을 사용하지 않고 :

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

짧은 문자열에는 사용할 수 있지만 공백이 많은 긴 문자열에서는 제대로 수행되지 않습니다.


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 "
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.