Пробелы, Соответствующие Регулярному Выражению-Java
Java API для регулярные выражения утверждает, что s будет соответствовать пробел. Так что регулярное выражение ss должно совпадать два пробела.
Pattern whitespace = Pattern.compile("ss");
matcher = whitespace.matcher(modLine);
while (matcher.find()) matcher.replaceAll(" ");
цель этого состоит в том, чтобы заменить все экземпляры двух последовательных пробелов одним пробелом. Однако это на самом деле не работает.
у меня есть серьезное непонимание регулярных выражений или термин "пробелы"?
8 ответов:
да, вам нужно захватить результат matcher.replaceAll ():
String result = matcher.replaceAll(" "); System.out.println(result);
вы не можете использовать
\sв Java, чтобы соответствовать пробелу в собственном собственном наборе символов, потому что Java не поддерживает свойство пробела Unicode-даже если это строго требуется для удовлетворения UTS#18'S RL1. 2! то, что у него есть, не соответствует стандартам, увы.Unicode определяет 26 кодовых точек как
\p{White_Space}: 20 из них являются различного рода\pZGeneralCategory=Разделитель, а остальные 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 Java’s native character set: Unicode */ String whitespace_charclass = "[" + whitespace_chars + "]"; /* A \S that actually works for Java’s native character set: Unicode */ String not_whitespace_charclass = "[^" + whitespace_chars + "]";теперь вы можете использовать
whitespace_charclass + "+"как шаблон в свойreplaceAll.
=begin soapboxизвините за все это. регулярные выражения Java просто не работают очень ну на свой родной набор символов, и поэтому вам действительно придется прыгать через экзотические обручи, чтобы заставить их работать.
и если вы думаете, что белое пространство плохо, вы должны увидеть, что вам нужно сделать, чтобы получить
\wи\bнаконец-то вести себя правильно!Да, это возможно, и да, это умопомрачительный беспорядок. Это даже благотворительность. Самый простой способ получить стандартную библиотеку регулярных выражений для Java-это перейти от JNI к материалам ICU. То, что делает Google для Android, потому что OraSun не соответствует.
если вы не хотите этого делать, но все еще хотите придерживаться Java, у меня есть библиотека перезаписи регулярных выражений переднего плана, которую я написал, что "исправляет" шаблоны Java, по крайней мере, чтобы они соответствовали требованиям RL1. 2a в UTS#18, Регулярных Выражений В Unicode.
=end soapbox
кажется, работает для меня:
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);
когда я отправил вопрос на форум Regexbuddy (regex developer application), я получил более точный ответ на мой вопрос Java:
" автор сообщения: Jan Goyvaerts
в Java сокращения \s, \d и \w включают только символы ASCII. ... Это не ошибка в Java, а просто одна из многих вещей, которые вы должны знать при работе с регулярными выражениями. Чтобы соответствовать всем пробелам Юникода, а также разрывам строк, вы можете использовать [\s\p{Z}] в Java. RegexBuddy еще не поддерживает Java-специфические свойства, такие как \P{javaSpaceChar} (который соответствует точно таким же символам, как [\s\p{Z}]).
... \s\S будет соответствовать двум пробелам, если вход только ASCII. Реальная проблема заключается в коде OP, как указано в принятом ответе на этот вопрос."
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);это нормализует интервал до одного и также удалит начальные и конечные пробелы.
использование пробелов в RE-это боль, но я считаю, что они работают. Проблема OP также может быть решена с помощью StringTokenizer или метода split (). Однако, чтобы использовать RE (раскомментировать println () для просмотра того, как сопоставитель разбивает строку), вот пример кода:
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"
Comments