Ответ 1
Да, вам нужно взять результат matcher.replaceAll():
String result = matcher.replaceAll(" ");
System.out.println(result);
API Java для регулярных выражений утверждает, что \s
будет соответствовать пробелу. Поэтому регулярное выражение \\s\\s
должно соответствовать двум пробелам.
Pattern whitespace = Pattern.compile("\\s\\s");
matcher = whitespace.matcher(modLine);
while (matcher.find()) matcher.replaceAll(" ");
Цель состоит в том, чтобы заменить все экземпляры двух последовательных пробелов одним пространством. Однако это на самом деле не работает.
Имею ли я серьезное непонимание регулярных выражений или термин "пробелы"?
Да, вам нужно взять результат matcher.replaceAll():
String result = matcher.replaceAll(" ");
System.out.println(result);
Вы не можете использовать \s
в Java для сопоставления пробелов в своем собственном наборе символов, потому что Java не поддерживает свойство пробела Unicode - хотя это строго необходимо для соответствия RTS1.2 UTS # 18! У него, к сожалению, нет соответствия стандартам.
Unicode определяет 26 кодовых точек как \p{White_Space}
: 20 из них являются различными видами \pZ
GeneralCategory = Separator, а остальные 6 являются \p{Cc}
GeneralCategory = Control.
Пустое пространство является довольно стабильным свойством, и те же самые существуют практически всегда. Тем не менее, Java не имеет свойства, которое соответствует стандарту Unicode для них, поэтому вы должны вместо этого использовать код, подобный этому:
String whitespace_chars = "" /* dummy empty string for homogeneity */
+ "\\u0009" // CHARACTER TABULATION
+ "\\u000A" // LINE FEED (LF)
+ "\\u000B" // LINE TABULATION
+ "\\u000C" // FORM FEED (FF)
+ "\\u000D" // CARRIAGE RETURN (CR)
+ "\\u0020" // SPACE
+ "\\u0085" // NEXT LINE (NEL)
+ "\\u00A0" // NO-BREAK SPACE
+ "\\u1680" // OGHAM SPACE MARK
+ "\\u180E" // MONGOLIAN VOWEL SEPARATOR
+ "\\u2000" // EN QUAD
+ "\\u2001" // EM QUAD
+ "\\u2002" // EN SPACE
+ "\\u2003" // EM SPACE
+ "\\u2004" // THREE-PER-EM SPACE
+ "\\u2005" // FOUR-PER-EM SPACE
+ "\\u2006" // SIX-PER-EM SPACE
+ "\\u2007" // FIGURE SPACE
+ "\\u2008" // PUNCTUATION SPACE
+ "\\u2009" // THIN SPACE
+ "\\u200A" // HAIR SPACE
+ "\\u2028" // LINE SEPARATOR
+ "\\u2029" // PARAGRAPH SEPARATOR
+ "\\u202F" // NARROW NO-BREAK SPACE
+ "\\u205F" // MEDIUM MATHEMATICAL SPACE
+ "\\u3000" // IDEOGRAPHIC SPACE
;
/* A \s that actually works for Javas native character set: Unicode */
String whitespace_charclass = "[" + whitespace_chars + "]";
/* A \S that actually works for Javas native character set: Unicode */
String not_whitespace_charclass = "[^" + whitespace_chars + "]";
Теперь вы можете использовать whitespace_charclass + "+"
в качестве шаблона в вашем replaceAll
.
Извини за все это. Регулярные выражения Javas просто не очень хорошо работают с собственным набором собственных символов, поэтому вам действительно нужно прыгать через экзотические обручи, чтобы заставить их работать.
И если вы думаете, что пробел - это плохо, вы должны увидеть, что вы должны сделать, чтобы \w
и \b
наконец-то вели себя правильно!
Да, это возможно, и да, это безумный беспорядок. Это даже благотворительность. Самый простой способ получить стандартизированную библиотеку регулярных выражений для Java - это использовать JNI для ICU. Это то, что Google делает для Android, потому что OraSuns не соответствует.
Если вы не хотите этого делать, но все же хотите придерживаться Java, у меня есть библиотека переписывания внешнего интерфейса, которую я написал, которая "исправляет" шаблоны Javas, по крайней мере, чтобы они соответствовали требованиям RL1.2a в UTS # 18., Юникод Регулярные выражения.
Для Java (не php, а не javascript, а не другого):
txt.replaceAll("\\p{javaSpaceChar}{2,}"," ")
когда я отправил вопрос на форум Regexbuddy (приложение-разработчик regex), я получил более точный ответ на мой вопрос в Java:
"Автор сообщения: Jan Goyvaerts
В Java сокращенные \s,\d и\w включают только символы ASCII.... Это не ошибка в Java, а просто одна из многих вещей, о которых вам нужно знать при работе с регулярными выражениями. Чтобы сопоставить все пробелы Unicode, а также разрывы строк, вы можете использовать [\ s\p {Z}] в Java. RegexBuddy еще не поддерживает специфичные для Java свойства, такие как \p {javaSpaceChar} (который соответствует тем же самым символам, что и [\ s\p {Z}]).
...\s\s будет соответствовать двум пробелам, если только вход ASCII. Реальная проблема связана с кодом OP, как указывается принятым ответом в этом вопросе.
Кажется, работает для меня:
String s = " a b c";
System.out.println("\"" + s.replaceAll("\\s\\s", " ") + "\"");
напечатает:
" a b c"
Я думаю, вы намеревались сделать это вместо своего кода:
Pattern whitespace = Pattern.compile("\\s\\s");
Matcher matcher = whitespace.matcher(s);
String result = "";
if (matcher.find()) {
result = matcher.replaceAll(" ");
}
System.out.println(result);
Pattern whitespace = Pattern.compile("\\s\\s");
matcher = whitespace.matcher(modLine);
boolean flag = true;
while(flag)
{
//Update your original search text with the result of the replace
modLine = matcher.replaceAll(" ");
//reset matcher to look at this "new" text
matcher = whitespace.matcher(modLine);
//search again ... and if no match , set flag to false to exit, else run again
if(!matcher.find())
{
flag = false;
}
}
Для вашей цели вы можете использовать этот snnippet:
import org.apache.commons.lang3.StringUtils;
StrintUtils.StringUtils.normalizeSpace(string);
это нормализует интервал до одинарного, а также удаляет начальные и конечные пробелы.
Для вашей цели вы можете использовать этот snnippet:
import org.apache.commons.lang3.StringUtils;
StrintUtils.StringUtils.normalizeSpace(string);
это нормализует интервал до одинарного, а также удаляет начальные и конечные пробелы.
String sampleString = "Привет, мир!"; sampleString.replaceAll("\ s {2}", ""); //заменяет ровно два последовательных пробела
sampleString.replaceAll("\ s {2,}", ""); // заменяет два или более последовательных пробелов
Использование пробелов в RE - это боль, но я считаю, что они работают. Проблема OP также может быть решена с помощью метода StringTokenizer или split(). Однако, чтобы использовать RE (раскомментируйте println(), чтобы посмотреть, как разветкитель разбивает String), вот пример кода:
import java.util.regex.*;
public class Two21WS {
private String str = "";
private Pattern pattern = Pattern.compile ("\\s{2,}"); // multiple spaces
public Two21WS (String s) {
StringBuffer sb = new StringBuffer();
Matcher matcher = pattern.matcher (s);
int startNext = 0;
while (matcher.find (startNext)) {
if (startNext == 0)
sb.append (s.substring (0, matcher.start()));
else
sb.append (s.substring (startNext, matcher.start()));
sb.append (" ");
startNext = matcher.end();
//System.out.println ("Start, end = " + matcher.start()+", "+matcher.end() +
// ", sb: \"" + sb.toString() + "\"");
}
sb.append (s.substring (startNext));
str = sb.toString();
}
public String toString () {
return str;
}
public static void main (String[] args) {
String tester = " a b cdef gh ij kl";
System.out.println ("Initial: \"" + tester + "\"");
System.out.println ("Two21WS: \"" + new Two21WS(tester) + "\"");
}}
Он производит следующее (компиляция с javac и запуск в командной строке):
% java Two21WS Начальное: "a b cdef gh ij kl" Two21WS: "a b cdef gh ij kl"