2013-03-19 1 views
7

У меня есть этот входной строки (с указанной вкладки, пробелы, переносы строк):Удалить все пробелы из строки, но сохранить ОДНУ строку


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








    Another test again. 

[Изменить]: Я должен был обеспечить строку для лучше тестирование как StackOverflow удаляет все специальные символы (вкладки, ...)

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

И я хочу, чтобы достичь этого состояния:


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

Любые идеи? Можно ли это сделать с помощью регулярных выражений?

replaceAll("\\s+", " ") НЕ ТО, что я ищу. Если это регулярное выражение сохранит ровно 1 новую строку существующих, было бы идеально.

Я попробовал это, но это, кажется неоптимальным мне ...:

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

Я думаю, что вы должны сделать некоторую логику для этого. Вам нужно искать символ небелого пробела после 1 пробела. и поиск символа без пробела после новой строки. –

+0

Какая логика вы хотите? Обрезание последовательных пробелов до 1 пробела? –

+0

@BlackMaggie да, что суммирует его, я думаю .. – friesoft

ответ

13

В одном регулярном выражении (плюс небольшой пластырь для вкладок):

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

Регулярное выражение выглядит устрашающе, но на самом деле распадается хорошо в эти части, которые OR-е изд вместе:

  • ^\s+ – матч Пробелы в начале;
  • \s+$ – сопоставление пробелов в конце;
  • \s*(\n)\s* – сопоставление пробелов, содержащих новую строку, и захват этой строки новой строки;
  • (\s)\s* – матч пробел, захват первого символа пробела.

Результат будет соответствовать двум группам захвата, но только одна из групп может быть непустой за раз. Это позволяет мне заменить матч "$1$2", что означает «объединить две группы захвата».

Единственная оставшаяся проблема в том, что я не могу заменить вкладку пространством с использованием этого подхода, поэтому я исправляю это с помощью замены простого символа без регулярного выражения.

+0

@MarkoTopolnik: спасибо за объяснение :) – friesoft

2

Если я правильно понимаю, вы просто хотите, чтобы заменить последовательность символов новой строки с одной строки. Поэтому замените \n\n* на \n (с соответствующими флагами). Если в строках много пробелов, просто удалите пробелы (^\s\s*$ с многострочным режимом), а затем замените новые строки.

Редактировать: Единственная проблема здесь в том, что некоторые новые строки могут оставаться здесь и там, поэтому вам нужно быть осторожными, чтобы сначала свернуть места, а затем исправить проблему с пустой строкой.Вы можете обрезать его дальше вниз в возможно один регулярное выражение, но это легче читать с этими тремя:

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

Это также верно работает в моем случае :) Придется попробовать больше testdata – friesoft

0

Почему бы вам не сделать

String[] lines = split(s,"\n") 
String[] noExtraSpaces = removeSpacesInEachLine(lines) 
String result = join(noExtraSpaces,"\n") 

Не забудьте https://softwareengineering.stackexchange.com/questions/10998/what-does-the-jamie-zawinskis-quotation-about-regular-expressions-mean

+0

Что относительно '' xx \ n \ n \ n yy "'? –

+0

@MarkoTopolnik хорошо, это зависит, если вам нужно сохранить пустые строки или удалить их. –

+0

Вы уверены, что действительно читаете вопрос о OP? –

2

Сначала замените все новыми линиями с одной новой линией, затем замените пробелами, но не новые линии, последняя вещь, вы должны удалить все пробелы из начала строки:

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

Выход:

This is a real 
test !! 
bye 
+0

@MarounMaroun для меня удаляет все пробелы.Я только что добавил примеры строк (содержащих правильные escape-символы). – friesoft

5

В 4 этапа:

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

Очень приятно :) Это оставляет один пробел в конце первой строки, но помимо этого это работает :) и даже прокомментировал :) – friesoft

+0

Единственные проблемы, с которыми я столкнулся, заключались в том, чтобы оставить одно место в конце строки, если бы были какие-то пробелы там, и оставляя единственную новую строку в начале/конце, если строка имела какие-либо завершающие символы новой строки. Я только что исправил (наконец-то надеюсь :)) – MBO