2009-06-19 2 views
1

Gibt es eine gute Möglichkeit, Token zu extrahieren, die mit einer vordefinierten Zeichenfolge beginnen und mit einer vordefinierten Zeichenfolge enden?Suchen von Token in einer Java-Zeichenfolge

Angenommen, die Startzeichenfolge ist "[" und die Endzeichenfolge ist "]". Wenn ich die folgende Zeichenfolge haben:

"Hallo [Welt] diese [[ist] me"

Der Ausgang sein soll:

token [0] = "Welt"

token [ 1] = "[ist"

(Anmerkung: das zweite Token eine 'Start' Zeichenfolge in es hat)

+0

Sind Ihre Token ein Zeichen nur oder dürfen sie länger sein? – glmxndr

+0

kann länger sein - mein Beispiel war der Einfachheit halber aber die Start-Zeichenfolge könnte "foo" und die End-Zeichenfolge könnte "bar" sein. – digiarnie

+0

Sieht aus wie Apache Commons Lang - StringUtilsStringsBetween (string, öffnen, schließen) ist, was Sie brauchen. Funktioniert gemäß obiger Anforderung, siehe Antwort unten für weitere Details. – Jon

Antwort

5

glaube ich Ihnen die Apache Commons Lang Funktion verwenden können, die in existiert:

substringsBetween(java.lang.String str, 
        java.lang.String open, 
        java.lang.String close) 

Die API-Dokumentation sagen es:

Suchbegriffe ein String für Substrings begrenzt durch ein Start- und End-Tag, , das alle übereinstimmenden Teilstrings in ein Array zurückgibt.

Die Commons Lang substringsBetween API ist hier zu finden:

http://commons.apache.org/lang/apidocs/org/apache/commons/lang/StringUtils.html#substringsBetween(java.lang.String,%20java.lang.String,%20java.lang.String)

0

StringTokenizer Stellen sie die Suchzeichenfolge? "[]" und das "schließen Token" Flag auf 012.und ich denke du bist eingestellt.

+0

Entschuldigung, welche Methode ist das? Ich sehe nichts mit etwas wie "include tokens" in der Signatur – digiarnie

+0

Ich kann nicht scheinen, dass in den Dokumenten entweder zu finden: http://java.sun.com/j2se/1.4.2/docs/api/ java/util/StringTokenizer.html – Sev

+1

Es ist in der 3 Argumente Konstruktor. Nichtsdestoweniger wird das Ergebnis {"Hallo", "[", "Welt", "]", "Dies", "[", "[", "Ist", "]", "Ich"} sein, also zusätzliche Arbeit muss stattfinden. –

0

Normale Zeichenfolge Tokenizer funktioniert nicht für seine Anforderung, aber Sie müssen zwicken oder schreiben Sie Ihre eigenen.

0

Es gibt eine Möglichkeit, dies zu tun. Es ist nicht besonders schön. Es geht darum, die Zeichenfolge Zeichen für Zeichen zu durchlaufen. Wenn du ein "[" erreichst, fängst du an, die Charaktere in ein neues Token zu setzen. Wenn du ein "]" erreichst, hörst du auf. Dies würde am besten unter Verwendung einer Datenstruktur, nicht eines Arrays, erfolgen, da Arrays von statischer Länge sind.

Eine andere Lösung, die möglicherweise möglich ist, ist die Verwendung von Regexen für die Split-Split-Methode des Strings. Das einzige Problem, das ich habe, ist mit einer Regex zu kommen, die sich teilen würde, wie Sie es wollen. Was ich mir vorstellen kann, ist {] Zeichenkette [] XOR (Zeichenkette [] XOR (] Zeichenkette) Jede Klammer steht für eine andere Regex. Sie sollten sie in dieser Reihenfolge auswerten, damit Sie nichts versehentlich entfernen. Ich bin nicht vertraut mit Regexes in Java, also habe ich "Zeichenkette" verwendet, um anzuzeigen, dass es Zeichen zwischen den Klammern gibt.

+0

yeah Ich dachte, dass Charakter für Charakter vielleicht die Lösung sein müsste, aber ich hatte gehofft, dass ich das möglichst vermeiden sollte - besonders wenn es eine elegante, bereits existierende API für das gab, was ich schon wollte. – digiarnie

0

Versuchen Sie einen regulären Ausdruck wie:

(.*?\[(.*?)\]) 

Die zweite Erfassung aller Informationen zwischen dem Satz [] enthalten sollte. Dies funktioniert jedoch nicht ordnungsgemäß, wenn die Zeichenfolge verschachtelt [] enthält.

1

Hier ist die Art, wie ich gehen würde, um Abhängigkeit von Commons lang zu vermeiden.

public static String escapeRegexp(String regexp){ 
    String specChars = "\\$.*+?|()[]{}^"; 
    String result = regexp; 
    for (int i=0;i<specChars.length();i++){ 
     Character curChar = specChars.charAt(i); 
     result = result.replaceAll(
      "\\"+curChar, 
      "\\\\" + (i<2?"\\":"") + curChar); // \ and $ must have special treatment 
    } 
    return result; 
} 

public static List<String> findGroup(String content, String pattern, int group) { 
    Pattern p = Pattern.compile(pattern); 
    Matcher m = p.matcher(content); 
    List<String> result = new ArrayList<String>(); 
    while (m.find()) { 
     result.add(m.group(group)); 
    } 
    return result; 
} 


public static List<String> tokenize(String content, String firstToken, String lastToken){ 
    String regexp = lastToken.length()>1 
        ?escapeRegexp(firstToken) + "(.*?)"+ escapeRegexp(lastToken) 
        :escapeRegexp(firstToken) + "([^"+lastToken+"]*)"+ escapeRegexp(lastToken); 
    return findGroup(content, regexp, 1); 
}   

es wie folgt verwendet:

String content = "hello[world]this[[is]me"; 
List<String> tokens = tokenize(content,"[","]"); 
+0

Warum das Rad neu erfinden? – Jon

+1

Weil wir in einer freien Welt leben. Und weil Sie vielleicht nicht eine ganze Bibliothek für eine Methode verwenden möchten. Und weil ich es so mag. Glücklich ? – glmxndr

0

StringTokenizer es nicht für das angegebene Verhalten geschnitten wird. Du brauchst deine eigene Methode.Etwas wie:

public List extractTokens(String txt, String str, String end) { 
    int      so=0,eo; 
    List      lst=new ArrayList(); 

    while(so<txt.length() && (so=txt.indexOf(str,so))!=-1) { 
     so+=str.length(); 
     if(so<txt.length() && (eo=txt.indexOf(end,so))!=-1) { 
      lst.add(txt.substring(so,eo); 
      so=eo+end.length(); 
      } 
     } 
    return lst; 
    } 
0

Der reguläre Ausdruck \\[[\\[\\w]+\\] gibt uns [Welt] und [[ist]