Этот код похож на replaceAll(regex, replacement)
.Проблема в том, что $
не только особый в аргументе regex , но также и в замене , где его можно использовать как ссылку для сопоставления из групп, подобных $x
(где x
является идентификатором группы) или ${groupName}
, если ваше регулярное выражение имеет (?<groupName>subregex)
.
Это позволяет нам писать код, подобный
String doubled = "abc".replaceAll(".", "$0$0");
System.out.println(doubled); //prints: aabbcc
, который заменит каждый символ двумя его копиями, поскольку каждый символ будет сопоставляться с .
и помещаться в группу 0, поэтому $0$0
представляет два повторения этого сопоставленного символа.
Но в вашем случае у вас есть $
в вашем text
, поэтому, когда он совпадает, вы заменяете его на себя, поэтому вы используете вместо $
без какой-либо информации об идентификаторе группы (или имени группы), что приводит к IllegalArgumentException: Illegal group reference
.
Решение состоит в том, чтобы избежать этого $
в замене часть .Вы можете сделать это вручную, с помощью \
, но лучше использовать метод, разработанный для этой цели Matcher#quoteReplacement
(в случае, если регулярное выражение будет развиваться, и вам нужно будет избегать больше вещей, этот метод должен развиватьсявместе с движком регулярных выражений, который впоследствии избавит вас от неприятностей)
Поэтому попробуйте изменить код на
public String replace(String text) {
Matcher m = p.matcher(text);
String replacement = m.replaceAll(match -> {
if (m.group(1) == null) {
return Matcher.quoteReplacement(m.group());
// ^^^^^^^^^^^^^^^^^^^^^^^^
} else {
return Matcher.quoteReplacement("(" + match.group(1) + ")");
// ^^^^^^^^^^^^^^^^^^^^^^^^
}
});
return replacement;
}
}