2013-03-19 21 views
7

Mam ten ciąg wejściowy (zawierajacego zaczepy, spacji linebreaks):Usuń wszystkie spacje z łańcucha, ale zawsze o jeden przełamane


 That  is a test.    
    seems to work  pretty good? working. 








    Another test again. 

[Edit]: I powinien dostarczyły ciąg dla lepiej testowanie jak stackoverflow usuwa wszystkie znaki specjalne (zakładki, ...)

String testContent = "\n\t\n\t\t\t\n\t\t\tDas  ist ein Test.\t\t\t \n\tsoweit scheint das \t\tganze zu? funktionieren.\n\n\n\n\t\t\n\t\t\n\t\t\t  \n\t\t\t  \n \t\t\t\n \tNoch ein Test.\n \t\n \t\n \t"; 

I chcę, aby osiągnąć ten stan:


That is a test. 
seems to work pretty good? working. 
Another test again. 

String expectedOutput = "Das ist ein Test.\nsoweit scheint das ganze zu? funktionieren.\nNoch ein Test.\n"; 

Jakieś pomysły? Czy można to osiągnąć za pomocą wyrażeń regularnych?

replaceAll("\\s+", " ") NIE jest tym, czego szukam. Jeśli to wyrażenie zachowałoby dokładnie 1 linię nowej istniejącej, byłoby idealnie.

Próbowałem tego, ale wydaje mi suboptimal ...:

BufferedReader bufReader = new BufferedReader(new StringReader(testContent)); 
String line = null; 
StringBuilder newString = new StringBuilder(); 
while ((line = bufReader.readLine()) != null) { 
    String temp = line.replaceAll("\\s+", " "); 
    if (!temp.trim().equals("")) { 
     newString.append(temp.trim()); 
     newString.append("\n"); 
    } 
} 
+0

Myślę, że musisz zrobić jakąś logikę dla tego .. musisz szukać znaku spoza tablicy po 1 spacji. i po znaku nowej linii szukaj znaku spacji. –

+0

Jaka jest logika? Przycinanie kolejnych białych znaków do 1 spacji? –

+0

@BlackMaggie tak, podsumowuje to myślę, że ... – friesoft

Odpowiedz

13

W jednym regex (plus mała łatka na zakładki):

input.replaceAll("^\\s+|\\s+$|\\s*(\n)\\s*|(\\s)\\s*", "$1$2") 
    .replace("\t"," "); 

regex wygląda trudne, ale w rzeczywistości rozkłada się ładnie do tych części, które są lub-ed razem:

  • ^\s+ – mecz białych na początku;
  • \s+$ – dopasować białe spacje na końcu;
  • \s*(\n)\s* – dopasowuje spacje zawierające znak nowej linii i przechwytuje tę linię;
  • (\s)\s* – Dopasuj białe spacje, przechwytując pierwszy znak odstępu.

Wynik będzie zgodny z dwiema grupami przechwytywania, ale tylko jedna z grup może być niepusta na raz. To pozwala mi zastąpić mecz przez "$1$2", co oznacza "połączenie dwóch grup przechwytywania".

Jedyny pozostały problem polega na tym, że nie mogę zastąpić tabulatora odstępem za pomocą tego podejścia, więc naprawię to za pomocą prostego zastępowania znaków bez regex.

+0

@MarkoTopolnik: dzięki za wyjaśnienie :) – friesoft

2

Jeśli dobrze rozumiem, chcesz po prostu wymienić następstwo nowych linii z jedną linią. Więc zamień \n\n* na \n (z odpowiednimi flagami). Jeśli w liniach jest dużo spacji, po prostu usuń białe znaki (^\s\s*$ z trybem multilinii), a następnie zamień znaki nowej linii.

Edytuj: Edycja: Jedyny problem polega na tym, że niektóre linie mogą pozostać tu i tam, więc musisz uważać, aby najpierw zwinąć spacje, a następnie naprawić problem z pustą linią.Możesz przyciąć ją dalej w prawdopodobnie jednym regex, ale łatwiej jest odczytać z tych trzech:

Pattern spaces = Pattern.compile("[\t ]+"); 
Pattern emptyLines = Pattern.compile("^\\s+$?", Pattern.MULTILINE); 
Pattern newlines = Pattern.compile("\\s*\\n+"); 
System.out.print(
     newlines.matcher(emptyLines.matcher(spaces.matcher(
     input).replaceAll(" ")).replaceAll("")).replaceAll("\n")); 
+0

Działa to również poprawnie w moim przypadku :) Będą musiały spróbować więcej testdata – friesoft

2

Najpierw wymień wszystkie nowe linie z jedną nową linię, a następnie zastąp przestrzenie, ale nie nowe linie, ostatnią rzeczą, należy usunąć wszystkie białe spacje z początku łańcucha:

String test = "  This is    a real\n\n\n\n\n\n\n\n\n test !!\n\n\n bye"; 
test = test.replaceAll("\n+", "\n"); 
test = test.replaceAll("((?!\n+)\\s+)", " "); 
test = test.replaceAll("((?!\n+)\\s+)", ""); 

wyjściowa:

This is a real 
test !! 
bye 
+0

@MarounMaroun dla mnie usuwa wszystkie spacje.Właśnie dodałem przykład Strings (zawierający właściwe znaki escape). – friesoft

5

w 4 krokach:

text 
    // 1. compress all non-newline whitespaces to single space 
    .replaceAll("[\\s&&[^\\n]]+", " ") 
    // 2. remove spaces from begining or end of lines 
    .replaceAll("(?m)^\\s|\\s$", "") 
    // 3. compress multiple newlines to single newlines 
    .replaceAll("\\n+", "\n") 
    // 4. remove newlines from begining or end of string 
    .replaceAll("^\n|\n$", "") 
+0

Bardzo ładne :) Pozostawia to puste na końcu pierwszej linii, ale obok tego działa :), a nawet komentowane :) – friesoft

+0

Jedynymi problemami, na które moje rozwiązanie polega: pozostawieniem pojedynczej spacji na końcu linii, jeśli były jakieś spacje tam i pozostawiając pojedynczy znak nowej linii na początku/końcu, jeśli ciąg znaków zawierał jakiekolwiek ciągnące znaki nowej linii. Właśnie to naprawiłem (nareszcie mam nadzieję :)) – MBO