2009-06-19 5 views
1

Existe-t-il un moyen agréable d'extraire des jetons commençant par une chaîne prédéfinie et se terminant par une chaîne prédéfinie? Par exemple, supposons que la chaîne de départ soit "[" et que la chaîne de fin soit "]". Par exemple, disons que la chaîne de départ est "["]. Si j'ai la chaîne suivante:Recherche de jetons dans une chaîne Java

"bonjour [monde] ce [[est] moi"

La sortie doit être:

jeton [0] = "world"

jeton [ 1] = "[est"

(note: le deuxième jeton est une chaîne 'start' en elle)

+0

-ce que vos jetons un caractère seulement ou peut-il être plus long? – glmxndr

+0

peut être plus long - mon exemple était pour la simplicité mais la chaîne de début pourrait être "foo" et la chaîne de fin pourrait être "barre". – digiarnie

+0

On dirait que Apache Commons Lang - StringUtils.substringsBetween (string, open, close) est ce dont vous avez besoin. Fonctionne comme indiqué ci-dessus, voir la réponse ci-dessous pour plus de détails. – Jon

Répondre

5

Je pense que vous pouvez utiliser la fonction Apache Commons Lang qui existe dans :

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

Les API docs disent que:

Recherches une chaîne pour les sous-chaînes délimitées par une balise de début et de fin, renvoyant toutes les sous-chaînes correspondantes dans un tableau.

L'API Commons Lang substringsBetween se trouvent ici:

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

0

StringTokenizer Définissez la chaîne de recherche? flag "[]" et "comprennent les jetons" à false et je pense que vous êtes prêt.

+0

Désolé, quelle méthode est-ce? Je ne vois rien avec quelque chose comme 'inclure des jetons' dans la signature – digiarnie

+0

Je n'arrive pas à trouver cela dans les docs: http://java.sun.com/j2se/1.4.2/docs/api/ java/util/StringTokenizer.html – Sev

+1

Il est dans le constructeur de 3 arguments. Néanmoins, le résultat sera {"hello", "[", "world", "]", "this", "[", "[", "est", "]", "moi"} doit avoir lieu. –

0

Le tokenizer de chaîne normale ne fonctionnera pas pour son exigence mais vous devez l'ajuster ou écrire le vôtre.

0

Il y a une façon de le faire. Ce n'est pas particulièrement joli. Ce que cela implique est de passer par la chaîne caractère par caractère. Lorsque vous atteignez un "[", vous commencez à placer les caractères dans un nouveau jeton. Lorsque vous atteignez un "]", vous arrêtez. Cela serait mieux fait en utilisant une structure de données pas un tableau puisque les tableaux sont de longueur statique.

Une autre solution qui peut être possible consiste à utiliser des regex pour la méthode split split de la chaîne. Le seul problème que j'ai est de trouver une regex qui se diviserait comme vous le souhaitez. Ce que je peux trouver est {] chaîne de caractères [) XOR (chaîne de caractères [) XOR (] chaîne de caractères) Chaque ensemble de parenthèses dénote une regex différente. Vous devriez les évaluer dans cet ordre afin de ne pas supprimer accidentellement tout ce que vous voulez. Je ne suis pas familier avec les expressions rationnelles en Java, donc j'ai utilisé "chaîne de caractères" pour indiquer qu'il y a des caractères entre les parenthèses.

+0

ouais je pensais que caractère par caractère pourrait être la solution mais j'espérais éviter cela si possible - surtout s'il y avait une API préexistante élégante pour ce que je veux déjà. – digiarnie

0

Essayez une expression régulière comme:

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

La seconde capture doit contenir toutes les informations entre l'ensemble de []. Cela ne fonctionnera cependant pas correctement si la chaîne contient imbriqué [].

1

Voici la façon dont j'irais pour éviter la dépendance aux langages communs.

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

utiliser comme ceci:

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

Pourquoi réinventer la roue? – Jon

+1

Parce que nous vivons dans un monde libre. Et parce que vous ne voudrez peut-être pas utiliser toute une bibliothèque pour une méthode. Et parce que j'aime ça de cette façon. Content ? – glmxndr

0

StringTokenizer ne sera pas coupé pour le comportement spécifié. Vous aurez besoin de votre propre méthode.Quelque chose comme:

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

L'expression régulière \\[[\\[\\w]+\\] nous donne [monde] et [[est]

Questions connexes