Java регулярное выражение самое короткое соответствие - PullRequest
0 голосов
/ 14 сентября 2018

У меня есть следующая строка, (a.1) (b.2) (c.3) (d.4).Я хочу изменить его на (1) (2) (3) (4).Я использую следующий метод.

str.replaceAll("\(.*[.](.*)\)","($1)").И я получаю только (4).Какой правильный метод?

Спасибо

Ответы [ 4 ]

0 голосов
/ 14 сентября 2018

Основная причина

Вы хотите сопоставить () -ограниченные подстроки, но используете .* шаблон жадных точек, который может соответствовать любым 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)"
0 голосов
/ 14 сентября 2018

попробуйте этот, он будет соответствовать любым алфавитам, . и " и заменит их все пустыми ""

str.replaceAll("[a-zA-Z\\.\"]", "") 


Редактировать:

Вы также можете использовать [^\\d)(\\s], чтобы сопоставить все символы, которые не являются числом, пробелом и )(, и заменить их все на пустую "" строку

String str  = "(a.1) (b.2) (c.3) (d.4)";
System.out.println(str.replaceAll("[^\\d)(\\s]",""));
0 голосов
/ 14 сентября 2018

Пара вещей здесь.Во-первых, ваши экранированные скобки неверны.В строковых литералах Java обратная косая черта сама по себе является escape-символом. Это означает, что вам необходимо использовать \\( для представления \( в регулярном выражении.

Я думаю, что ваш вопрос заключается в том, как выполнять несжадные совпадения в регулярном выражении.Используйте ? для указания не жадного соответствия;Например, *? означает «ноль или более раз, но как можно меньше раз».

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

String test = "(a.1) (b.2) (c.3) (d.4)";
String replaced = test.replaceAll("\\(.*?[.](.*?)\\)", "($1)");
System.out.println(replaced); // "(1) (2) (3) (4)"
0 голосов
/ 14 сентября 2018

Попробуйте это

str.replaceAll("[A-Za-z0-9]+\.","");

[A-Za-z0-9] будет соответствовать верхний регистр, нижний регистр и цифры.Если вы хотите сопоставить что-либо до точки (.), Вы можете использовать .+ или .* вместо [A-Za-z0-9]+

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