Выражения регулярных выражений в Java, \\ s vs. \\ s +


96

В чем разница между следующими двумя выражениями?

x = x.replaceAll("\\s", "");
x = x.replaceAll("\\s+", "");

3
Квантификаторы, прочтите о них.
jn1kk

Ответы:


88

Первый соответствует одному пробелу, а второй соответствует одному или нескольким пробелам. Это так называемые квантификаторы регулярных выражений, и они выполняют такие сопоставления (взяты из документации ):

Greedy quantifiers
X?  X, once or not at all
X*  X, zero or more times
X+  X, one or more times
X{n}    X, exactly n times
X{n,}   X, at least n times
X{n,m}  X, at least n but not more than m times

Reluctant quantifiers
X?? X, once or not at all
X*? X, zero or more times
X+? X, one or more times
X{n}?   X, exactly n times
X{n,}?  X, at least n times
X{n,m}? X, at least n but not more than m times

Possessive quantifiers
X?+ X, once or not at all
X*+ X, zero or more times
X++ X, one or more times
X{n}+   X, exactly n times
X{n,}+  X, at least n times
X{n,m}+ X, at least n but not more than m times

20
Мне всегда нравилось, как они по отдельности описывают жадную, сопротивляющуюся и притяжательную версии каждого квантификатора, а затем говорят одно и то же обо всех трех. ;)
Алан Мур

60

Эти два replaceAllвызова всегда будут давать один и тот же результат, независимо от того, что это xтакое. Однако важно отметить, что эти два регулярных выражения не совпадают:

  • \\s - соответствует одиночному пробельному символу
  • \\s+ - соответствует последовательности из одного или нескольких символов пробела.

В этом случае это не имеет значения, поскольку вы заменяете все пустой строкой (хотя было бы лучше использовать \\s+с точки зрения эффективности). Если бы вы заменяли непустую строку, они вели бы себя по-разному.


Напишите в первой строке, если x - «Забронируйте домен и \ n \ n \ n \ n \ n \ n онлайн сегодня». Оба будут давать одинаковые результаты?
sofs1

3
@ user3705478 Оба будут давать одинаковые результаты, даже если будет несколько пробелов друг за другом. Разница заключается в том, как с этим справляются. Если у вас есть группа из (например) 3 пробелов, следующих друг за другом, \\ s + берет эту группу и превращает ее целиком в "", тогда как \\ s будет обрабатывать каждое пространство самостоятельно.
Денни

11

Прежде всего, вам нужно понять, что конечный результат обоих операторов будет одинаковым, то есть удалить все пробелы из данной строки.

Однако x.replaceAll("\\s+", "");это будет более эффективный способ обрезки пробелов (если строка может иметь несколько смежных пробелов) из-за потенциально меньшего количества замен из-за того, что регулярное выражение \\s+соответствует 1 или более пробелам одновременно и заменяет их пустой строкой.

Поэтому, даже если вы получаете одинаковый результат от обоих, лучше использовать:

x.replaceAll("\\s+", "");

2

Первое регулярное выражение будет соответствовать одному пробельному символу. Второе регулярное выражение неохотно будет соответствовать одному или нескольким пробельным символам. В большинстве случаев эти два регулярных выражения очень похожи, за исключением второго случая, когда регулярное выражение может соответствовать большей части строки, если оно предотвращает сбой сопоставления регулярного выражения. из http://www.coderanch.com/t/570917/java/java/regex-difference


Нацарапайте слово «неохотно». Этот вопрос \s+не \s+?похож на другой.
Алан Мур
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.