Java Regex vervangen door Capturing Group

Is er een manier om een ​​regexp te vervangen door gewijzigde inhoud van de capture-groep?

Voorbeeld:

Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher(text);
resultString = regexMatcher.replaceAll("$1"); // *3 ??

En ik wil graag alle exemplaren vervangen door $1 vermenigvuldigd met 3.

bewerken:

Het lijkt erop dat er iets mis is 🙁

Als ik gebruik

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();
}

Het genereert een IllegalStateException: Geen overeenkomst gevonden

Maar

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();
}

werkt prima, maar ik kan de $1 niet wijzigen 🙁

bewerken:

Nu werkt het 🙂


Antwoord 1, autoriteit 100%

Wat dacht je van:

if (regexMatcher.find()) {
    resultString = regexMatcher.replaceAll(
            String.valueOf(3 * Integer.parseInt(regexMatcher.group(1))));
}

Gebruik #find()om de eerste overeenkomst te krijgen. Daarna kun je #group(1)gebruiken om naar deze eerste overeenkomst te verwijzen en alle overeenkomsten te vervangen door de eerste maches-waarde vermenigvuldigd met 3.

En voor het geval u elke overeenkomst wilt vervangen door de waarde van die overeenkomst vermenigvuldigd met 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());

Misschien wil je door Matcher‘s documentatie, waar dit en nog veel meer dingen in detail worden behandeld.


Antwoord 2, autoriteit 13%

earl’s antwoord geeft je de oplossing, maar ik dacht ik voeg eraan toe wat het probleem is dat je IllegalStateExceptionveroorzaakt. Je roept group(1)aan zonder eerst een overeenkomende bewerking te hebben aangeroepen (zoals find()). Dit is niet nodig als u alleen $1gebruikt, aangezien de replaceAll()de overeenkomende bewerking is.


Antwoord 3, autoriteit 9%

Java 9 biedt een Matcher.replaceAll()die een vervangende functie accepteert:

resultString = regexMatcher.replaceAll(
        m -> String.valueOf(Integer.parseInt(m.group()) * 3));

Antwoord 4

Bron: java-implementation-of-rubys -gsub

Gebruik:

// 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);

Implementatie (opnieuw ontworpen):

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();
    }
}

Other episodes