2009-08-14 6 views
1

Possible en double:
Java Regex Replace with Capturing GroupJava Regex Remplacer par Capturing Groupe

Est-il possible de remplacer une expression rationnelle avec un contenu modifié du groupe de capture?

Exemple:

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

Et je voudrais remplacer tout événement avec 1 $ multiplié par 3.

modifier:

On dirait, quelque chose qui 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: Aucun résultat trouvé

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 très bien, mais je ne peux pas changer le 1 :(

Edit2 $:

maintenant , ça marche :)

+0

Incase autres utilisateurs rencontrent un problème similaire, pourriez-vous élaborer ce que vous avez fait pour corriger le problème? :) – doomspork

+0

Je ne saurais pas comment le faire en Java, mais en Perl c'est facile. :-P $ foo = '12 54 1 65 '; $ foo = ~ s/(\ d {1,2})/$ 1 * 3/par exemple; –

+0

ici était une réponse qui décrit comment le faire, je ne sais pas où il est maintenant ... (j'ai accepté une question qui résout le problème, mais a disparu.Etrange ...) – user

Répondre

14

La solution définitive à ce problème a été postée par Elliott Hughes sur son blog il y a quelques années. Elliott continue d'introduire des dépendances inutiles à d'autres classes dans la version en ligne, donc je posterai une version autonome ici (les dépendances sont seulement dans les tests dans la méthode main()).

import java.util.regex.*; 

/** 
* A Rewriter does a global substitution in the strings passed to its 
* 'rewrite' method. It uses the pattern supplied to its constructor, and is 
* like 'String.replaceAll' except for the fact that its replacement strings 
* are generated by invoking a method you write, rather than from another 
* string. This class is supposed to be equivalent to Ruby's 'gsub' when 
* given a block. This is the nicest syntax I've managed to come up with in 
* Java so far. It's not too bad, and might actually be preferable if you 
* want to do the same rewriting to a number of strings in the same method 
* or class. See the example 'main' for a sample of how to use this class. 
* 
* @author Elliott Hughes 
*/ 
public abstract class Rewriter 
{ 
    private Pattern pattern; 
    private Matcher matcher; 

    /** 
    * Constructs a rewriter using the given regular expression; the syntax is 
    * the same as for 'Pattern.compile'. 
    */ 
    public Rewriter(String regex) 
    { 
    this.pattern = Pattern.compile(regex); 
    } 

    /** 
    * Returns the input subsequence captured by the given group during the 
    * previous match operation. 
    */ 
    public String group(int i) 
    { 
    return matcher.group(i); 
    } 

    /** 
    * Overridden to compute a replacement for each match. Use the method 
    * 'group' to access the captured groups. 
    */ 
    public abstract String replacement(); 

    /** 
    * Returns the result of rewriting 'original' by invoking the method 
    * 'replacement' for each match of the regular expression supplied to the 
    * constructor. 
    */ 
    public String rewrite(CharSequence original) 
    { 
    this.matcher = pattern.matcher(original); 
    StringBuffer result = new StringBuffer(original.length()); 
    while (matcher.find()) 
    { 
     matcher.appendReplacement(result, ""); 
     result.append(replacement()); 
    } 
    matcher.appendTail(result); 
    return result.toString(); 
    } 



    public static void main(String... args) throws Exception 
    { 
    String str = "12 54 1 65"; 

    // anonymous subclass 
    Rewriter tripler = new Rewriter("(\\d{1,2})") 
    { 
     public String replacement() 
     { 
     int intValue = Integer.valueOf(group(1)); 
     return String.valueOf(intValue * 3); 
     } 
    }; 
    System.out.println(tripler.rewrite(str)); 

    // inline subclass 
    System.out.println(new Rewriter("(\\d{1,2})") 
    { 
     public String replacement() 
     { 
     int intValue = Integer.valueOf(group(1)); 
     return String.valueOf(intValue * 3); 
     } 
    }.rewrite(str)); 

    } 
} 
0

Non, vous ne pouvez pas fais ça avec regex. Regex n'a aucune notion de valeurs numériques, donc faire de l'arithmétique avec des nombres n'est pas possible (en supposant que vous vouliez convertir "12 54 1 65" en "36 162 3 195"). Notez qu'avec certaines implémentations de langages et regex vous pouvez le faire (Perl comme Chris posté), mais ce n'est pas une chose regex, et surtout pas une chose Java-regex. Vous avez dit que vous avez déjà résolu le problème, donc je suppose que vous êtes passé au mode "manuel", en convertissant chaque correspondance en entier et en multipliant cela par 3.