Основная причина
Вы хотите сопоставить ()
-ограниченные подстроки, но используете .*
шаблон жадных точек, который может соответствовать любым 0 или более символам (кроме разрыва строки)символы).Шаблон \(.*[.](.*)\)
будет соответствовать первому (
в (a.1) (b.2) (c.3) (d.4)
, затем .*
захватит всю строку, и при обратном отслеживании начнется попытка разместить текст для последующих обязательных подшаблонов.[.]
найдет последний .
в строке, предшествующий последней цифре, 4
.Затем (.*)
снова захватит всю оставшуюся строку, но поскольку )
требуется сразу после этого, из-за возврата назад последний (.*)
будет захватывать только 4
.
Почему ленивый / неохотный .*?
не является решением?
Даже если вы используете \(.*?[.](.*?)\)
, если есть (xxx)
как подстроки внутри строки, они будут сопоставляться с ожидаемыми совпадениями, так как .
соответствует любому символу, кроме символов разрыва строки.
Solution
.replaceAll("\\([^()]*\\.([^()]*)\\)", "($1)")
См. regex demo .[^()]
будет соответствовать только любому символу, НО (
и )
.
Подробности
\(
- (
char [^()]*
- класс отрицанных символов, соответствующий 0 или более символам, отличным от (
и )
\.
- точка ([^()]*)
-Группа 1 (ее значение позже упоминается с помощью $1
из шаблона замены): любые 0+ символов, кроме (
и )
\)
- )
char.
Демонстрационная версия Java :
List<String> strs = Arrays.asList("(a.1) (b.2) (c.3) (d.4)", "(a.1) (xxxx) (b.2) (c.3) (d.4)");
for (String str : strs)
System.out.println("\"" + str.replaceAll("\\([^()]*\\.([^()]*)\\)", "($1)") + "\"");
Вывод:
"(1) (2) (3) (4)"
"(1) (xxxx) (2) (3) (4)"