Regex заменить на счет матча

Я хотел бы заменить совпадение номером/индексом соответствия.

Есть ли способ в java regex flavor знать, какой номер совпадения соответствует текущему совпадению, поэтому я могу использовать String.replaceAll(regex, replacement)?

Пример: Замените [A-Z] на себя и свой индекс:

Input:  fooXbarYfooZ
Output: fooX1barY2fooZ3

т.е. этот вызов:

"fooXbarXfooX".replaceAll("[A-Z]", "$0<some reference to the match count>");

должен возвращать "fooX1barY2fooZ3"


Примечание. Я ищу заменяющую строку, которая может это сделать, если таковая существует.


Пожалуйста, не предоставляйте ответы, содержащие циклы или аналогичный код.


Отредактировано:

Я приму самый элегантный ответ, который работает (даже если он использует цикл). Нет текущих ответов
на самом деле работают.

Ответы

Ответ 1

Java regex не поддерживает ссылку на счетчик совпадений, поэтому это невозможно.

Ответ 2

Итерирование по входной строке требуется, так что цикл так или иначе неизбежен. Стандартный API не реализует метод, реализующий этот цикл, поэтому цикл должен быть в клиентском коде или в сторонней библиотеке.


Вот как код будет выглядеть как btw:

public abstract class MatchReplacer {

    private final Pattern pattern;

    public MatchReplacer(Pattern pattern) {
        this.pattern = pattern;
    }

    public abstract String replacement(MatchResult matchResult);

    public String replace(String input) {

        Matcher m = pattern.matcher(input);

        StringBuffer sb = new StringBuffer();

        while (m.find())
            m.appendReplacement(sb, replacement(m.toMatchResult()));

        m.appendTail(sb);

        return sb.toString();
    }
}

Использование:

public static void main(String... args) {
    MatchReplacer replacer = new MatchReplacer(Pattern.compile("[A-Z]")) {
        int i = 1;
        @Override public String replacement(MatchResult m) { 
            return "$0" + i++;
        }
    };
    System.out.println(replacer.replace("fooXbarXfooX"));
}

Вывод:

fooX1barX2fooX3

Ответ 3

Невозможно без циклов в Java...

Ответ 4

Ну, я не думаю, что это возможно без какого-либо цикла в Java.

String x = "fooXbarXfooX";
        int count = 0;
        while(x.contains("X"))
        x = x.replaceFirst("X", Integer.toString(count++));
        System.out.println(x);