Замена Java Regex с помощью группы захвата
Есть ли способ заменить регулярное выражение измененным содержимым группы захвата?
Пример:
Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher(text);
resultString = regexMatcher.replaceAll("$1"); // *3 ??
И я бы хотел заменить все вхождение на $1, умноженное на 3.
изменить
Похоже, что-то не так: (
Если я использую
Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher("12 54 1 65");
try {
String resultString = regexMatcher.replaceAll(regexMatcher.group(1));
} catch (Exception e) {
e.printStackTrace();
}
Он выдает исключение IllegalStateException: совпадение не найдено
Но
Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher("12 54 1 65");
try {
String resultString = regexMatcher.replaceAll("$1");
} catch (Exception e) {
e.printStackTrace();
}
работает нормально, но я не могу изменить $1: (
изменить
Теперь он работает:)
Ответы
Ответ 1
Как насчет:
if (regexMatcher.find()) {
resultString = regexMatcher.replaceAll(
String.valueOf(3 * Integer.parseInt(regexMatcher.group(1))));
}
Чтобы получить первое совпадение, используйте #find()
. После этого вы можете использовать #group(1)
для ссылки на это первое совпадение и заменить все совпадения на первое значение магов, умноженное на 3.
И в случае, если вы хотите заменить каждое соответствие на это значение соответствия, умноженное на 3:
Pattern p = Pattern.compile("(\\d{1,2})");
Matcher m = p.matcher("12 54 1 65");
StringBuffer s = new StringBuffer();
while (m.find())
m.appendReplacement(s, String.valueOf(3 * Integer.parseInt(m.group(1))));
System.out.println(s.toString());
Вы можете просмотреть Matcher
documentation, где подробно описано это и многое другое.
Ответ 2
Ответ на earl дает вам решение, но я думал, что добавлю, что проблема в том, что вызывает ваш IllegalStateException
. Вы вызываете group(1)
, не вызвав сначала операцию сопоставления (например, find()
). Это не нужно, если вы просто используете $1
, так как replaceAll()
- это операция сопоставления.
Ответ 3
Источник: java-implementation-of-rubys-gsub
Использование:
// Rewrite an ancient unit of length in SI units.
String result = new Rewriter("([0-9]+(\\.[0-9]+)?)[- ]?(inch(es)?)") {
public String replacement() {
float inches = Float.parseFloat(group(1));
return Float.toString(2.54f * inches) + " cm";
}
}.rewrite("a 17 inch display");
System.out.println(result);
// The "Searching and Replacing with Non-Constant Values Using a
// Regular Expression" example from the Java Almanac.
result = new Rewriter("([a-zA-Z]+[0-9]+)") {
public String replacement() {
return group(1).toUpperCase();
}
}.rewrite("ab12 cd efg34");
System.out.println(result);
Реализация (переработанная):
import static java.lang.String.format;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public abstract class Rewriter {
private Pattern pattern;
private Matcher matcher;
public Rewriter(String regularExpression) {
this.pattern = Pattern.compile(regularExpression);
}
public String group(int i) {
return matcher.group(i);
}
public abstract String replacement() throws Exception;
public String rewrite(CharSequence original) {
return rewrite(original, new StringBuffer(original.length())).toString();
}
public StringBuffer rewrite(CharSequence original, StringBuffer destination) {
try {
this.matcher = pattern.matcher(original);
while (matcher.find()) {
matcher.appendReplacement(destination, "");
destination.append(replacement());
}
matcher.appendTail(destination);
return destination;
} catch (Exception e) {
throw new RuntimeException("Cannot rewrite " + toString(), e);
}
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(pattern.pattern());
for (int i = 0; i <= matcher.groupCount(); i++)
sb.append(format("\n\t(%s) - %s", i, group(i)));
return sb.toString();
}
}
Ответ 4
Java 9 предлагает Matcher.replaceAll()
который принимает функцию замены:
resultString = regexMatcher.replaceAll(m -> String.valueOf(Integer.parseInt(m.group()) * 3));