2009-08-14 12 views
63

¿Hay alguna forma de reemplazar una expresión regular con contenido modificado del grupo de captura?Reemplazo de Java Regex con el grupo de captura

Ejemplo:

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

Y me gustaría para reemplazar todos los sucesos con $ 1 multiplicada por 3.

edición:

parece, algo anda mal :(

Si uso

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

lanza una IllegalStateException: No se encontró coincidencia

Pero

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

funciona bien, pero no puedo cambiar $ 1 :(

edición:

Ahora , está funcionando :)

+0

trabajando directamente en una cadena, por fin tenemos [esto] (http: // stackoverflow .com/a/6057820/1422630) –

Respuesta

73

Qué tal:

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

Para obtener la primera coincidencia, use #find(). Después de eso, puede utilizar #group(1) para referirse a este primer partido, y vuelva a colocar todos los partidos por el primer valor Maches multiplicado por 3.

Y en caso de que desee reemplazar cada coincidencia con el valor de ese partido multiplicado por 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()); 

Es posible que desee consultar Matcher's documentation, donde esto y mucho más se cubre en detalle.

+5

sí, pero pierde la cadena original. si es "a 1 2 3" no tendrá el a –

+18

¡Esto fue muy útil! Una adición es que si coincide un texto y sus coincidencias no están al final, deberá llamar a m.appendTail (s); – mezzie

+0

Tenga cuidado al buscar grupos con texto estático como Pattern.compile ("var myVar = \" (. *) \ ";"); - Reemplazará a todos los encontrados no solo al grupo.consulte también el enlace de John O. –

10

La respuesta de earl te da la solución, pero pensé que agregaría el problema que está causando tu IllegalStateException. Está llamando al group(1) sin haber llamado primero una operación de coincidencia (como find()). Esto no es necesario si solo está usando $1 ya que replaceAll() es la operación de coincidencia.

1

Fuente: java-implementation-of-rubys-gsub

Uso:

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

implementación (nuevo diseño):

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