2013-11-02 1 views
10

Ich bin auf der Suche nach einem sehr einfachen Weg, um das Äquivalent von etwas wie dem folgenden JavaScript-Code zu erhalten. Das heißt, ich möchte für jede Übereinstimmung eine bestimmte Transformationsfunktion aufrufen und das Ergebnis als Ersatzwert verwenden.Was entspricht Regex-Replace-with-Function-Evaluierung in Java 7?

var res = "Hello World!".replace(/\S+/, function (word) { 
    // Since this function represents a transformation, 
    // replacing literal strings (as with replaceAll) are not a viable solution. 
    return "" + word.length; 
}) 
// res => "5 6" 

Nur .. in Java. Und vorzugsweise als "single method" oder "template", die wiederverwendet werden können.

Antwort

10

Ihre Antwort ist in der Matcher#appendReplacement Dokumentation. Setzen Sie Ihren Funktionsaufruf einfach in die while-Schleife.

[Die appendReplacement-Methode] soll in einer Schleife zusammen mit den Methoden appendTail und find verwendet werden. Der folgende Code schreibt zum Beispiel ein Hund zwei Hunde auf dem Hof ​​zur Standard-Ausgabestrom:

Pattern p = Pattern.compile("cat"); 
Matcher m = p.matcher("one cat two cats in the yard"); 
StringBuffer sb = new StringBuffer(); 
while (m.find()) { 
    m.appendReplacement(sb, "dog"); 
} 
m.appendTail(sb); 
System.out.println(sb.toString()); 
+2

[Hier] (http://stackoverflow.com/a/1282099/20938) ist eine vollständigere Lösung. Es behandelt das Problem von Dollarzeichen und Backslashes, die von 'appendReplacement()' als speziell behandelt werden. –

0

nicht sicher, was Ihre genauen Anforderungen sind aber so etwas wie dies funktionieren könnte:

String res = ""; 
for (String piece : "hello world".split(" ")) 
    res += Integer.toString(piece.length()) + " "; 

Natürlich gibt es andere Möglichkeiten, dies zu schreiben, und Anpassungen, die abhängig von den Anforderungen vorgenommen werden können (z. B. ein genaueres Trennzeichen als ein Leerzeichen verwenden).

Für eine präzise Implementierung Ihres Snippets können Sie z. StreamTokenizer mit einem StringReader und einigen Wrappern, um die Trennzeichen zu analysieren und sie zwischen den Zählungen einzufügen.

+1

Während dies hier funktionieren würde, suche ich nach einer Lösung, die generisch bleiben kann (durch die Verwendung von Unterstützung für reguläre Ausdrücke). – user2864740

+0

Ah, ja, das wäre dann kein guter Weg das zu tun. –

6

Wenn ermöglicht Java 8 können Sie Lambda-Ausdrücke verwenden, einen JavaScript haben mag ersetzen:

String result = StringReplacer.replace("Hello World!", Pattern.compile("\\S+"), (Matcher m) -> { 
    return "" + m.group().length(); 
}); 

StringReplacer.java:

import java.util.regex.Matcher; 
import java.util.regex.Pattern; 

public class StringReplacer { 
    public static String replace(String input, Pattern regex, StringReplacerCallback callback) { 
     StringBuffer resultString = new StringBuffer(); 
     Matcher regexMatcher = regex.matcher(input); 
     while (regexMatcher.find()) { 
      regexMatcher.appendReplacement(resultString, callback.replace(regexMatcher)); 
     } 
     regexMatcher.appendTail(resultString); 

     return resultString.toString(); 
    } 
} 

StringReplacerCallback.java:

import java.util.regex.Matcher; 

public interface StringReplacerCallback { 
    public String replace(Matcher match); 
} 

Quelle: http://www.whitebyte.info/programming/string-replace-with-callback-in-java-like-in-javascript

+3

Sie könnten "Matcher.quoteReplacement" für die Ersetzungszeichenfolge aufrufen, um zu vermeiden, dass Schrägstriche und Dollarzeichen speziell behandelt werden. – Gareth

+0

@Gareth es wäre toll, wenn Sie das [gist] (https://gist.github.com/nickressler/42f8619f1a36eea25364) abzweigen könnten, verbessern Sie es und kommentieren Sie es mit dem Link. Ich werde dann den Post und meinen Kern so schnell wie möglich aktualisieren. –