81 votes

Remplacement d'un Regex Java par un groupe de capture

Existe-t-il un moyen de remplacer une regexp par le contenu modifié d'un groupe de capture ?

Exemple :

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

Et j'aimerais remplacer toute occurrence par 1 $ multiplié par 3.

éditer :

On dirait que quelque chose ne va pas :(

Si j'utilise

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

Il lance une IllegalStateException : Aucune correspondance trouvée

Mais

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

fonctionne bien, mais je ne peux pas changer le $1 :(

éditer :

Maintenant, ça marche :)

0 votes

En travaillant directement sur une chaîne de caractères, nous avons finalement este

83voto

earl Points 10428

Pourquoi pas :

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

Pour obtenir la première correspondance, utilisez #find() . Après cela, vous pouvez utiliser #group(1) pour faire référence à cette première correspondance, et remplacer toutes les correspondances par la première valeur de maches multipliée par 3.

Et au cas où vous voudriez remplacer chaque correspondance par la valeur de cette correspondance multipliée par 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());

Vous pouvez consulter Matcher Documentation de l'UE où ce sujet et bien d'autres sont traités en détail.

10 votes

Oui mais vous perdez la chaîne originale. si c'est "a 1 2 3 " vous n'aurez pas le a

21 votes

C'était plutôt utile ! Il faut ajouter que si vous faites correspondre un texte et que vos correspondances ne sont pas à la fin, vous devez appeler m.appendTail(s) ;

0 votes

Faites attention lorsque vous trouvez des groupes avec du texte statique autour comme Pattern.compile("var myVar=\"(.*)\" ;") ; - Il remplacera tout ce qui a été trouvé et pas seulement le groupe. voir aussi le lien de John O.

11voto

Draemon Points 15448

La réponse d'Earl vous donne la solution, mais j'ai pensé ajouter le problème qui cause votre problème. IllegalStateException . Vous appelez group(1) sans avoir préalablement appelé une opération de mise en correspondance (telle que find() ). Ce n'est pas nécessaire si vous utilisez seulement $1 depuis le replaceAll() est l'opération de mise en correspondance.

7voto

John O Points 1018

Il existe un exemple à ce sujet page de JavaPractices.com - voir le deuxième exemple, "Remplacement dynamique".

7voto

shmosel Points 4840

Java 9 offre une Matcher.replaceAll() qui accepte une fonction de remplacement :

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

1voto

Mykhaylo Adamovych Points 1907

Source : java-implementation-of-rubys-gsub

Utilisation :

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

Mise en œuvre (remaniée) :

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X