2009-08-14 16 views
63

Czy istnieje sposób na zastąpienie wyrażeń regularnych zmodyfikowaną zawartością grupy przechwytywania?Regex Java zastępuje grupę przechwytywania

Przykład:

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

I chciałbym, aby zastąpić wszystkie wystąpienia $ 1 pomnożona przez 3.

edit:

Wygląda na to, że coś jest źle :(

Jeśli używam

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

To rzuca IllegalStateException: Nie znaleziono

Ale

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

działa poprawnie, ale nie mogę zmienić $ 1 :(

EDIT:

teraz , działa :)

+0

przez pracę bezpośrednio na sznurku, mamy wreszcie [to] (http: // stackoverflow .com/a/6057820/1422630) –

Odpowiedz

73

Co powiesz na:

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

Aby uzyskać pierwszy mecz, należy użyć #find(). Po tym, można użyć #group(1) odnieść się do tego pierwszego spotkania i zastąpić wszystkie mecze od pierwszej wartości maches pomnożona przez 3.

A w przypadku, gdy chcesz zastąpić każdy mecz z wartością pasujących pomnożona przez 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()); 

Możesz przejrzeć Matcher's documentation, gdzie szczegółowo omówiono to i wiele innych rzeczy.

+5

tak, ale tracisz oryginalny ciąg znaków. jeśli jest to "a 1 2 3", nie będziesz miał –

+18

To było całkiem pomocne! Jednym dodatkiem jest to, że jeśli twoje dopasowanie tekstu i twoich dopasowań nie jest na końcu, musisz zadzwonić m.appendTail (s); – mezzie

+0

Należy zachować ostrożność podczas wyszukiwania grup o statycznym tekście, takich jak Pattern.compile ("var myVar = \" (. *) \ ";"); - Zastąpi wszystkie znalezione nie tylko grupy.patrz także link do Johna O. –

10

Odpowiedź earla daje rozwiązanie, ale pomyślałem, że dodam, jaki jest problem, który powoduje twoją IllegalStateException. Dzwonisz pod numer group(1) bez uprzedniego wywołania operacji dopasowania (takiej jak find()). Nie jest to konieczne, jeśli używasz tylko $1, ponieważ replaceAll() jest zgodną operacją.

1

Źródło: java-implementation-of-rubys-gsub

Zastosowanie:

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

Realizacja (przebudowany):

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(); 
    } 
} 
Powiązane problemy