9
votes

Tokenize une chaîne avec un espace en Java

Je veux hotkenize une chaîne comme celle-ci xxx

je ne peux pas scinder en fonction de ce xxx

aucune idée de quoi que je reçois des jetons comme xxx


3 commentaires

Ne pouviez pas simplement utiliser une regex pour diviser par des espaces sauf si vous êtes à l'intérieur d'une citation (pas que je sais regex, mais je suis à peu près sûr que vous pouvez le faire).


Votre code fonctionne parfaitement ici à l'aide de JDK 1.6.0_13


@Lepad ci-dessus code donnera [a = b, c = '123, 456', D = 777, e = 'uij, yyy']


11 Réponses :


9
votes

Le moyen le plus simple de le faire est de mettre en œuvre une simple machine à états finie. En d'autres termes, traiter la chaîne un caractère à la fois:

  • Lorsque vous frappez un espace, cassez un jeton;
  • Lorsque vous avez frappé une citation, continuez à obtenir des personnages jusqu'à ce que vous ayez frappé une autre citation.

2 commentaires

Une machine d'état bien finie équivaut à une expression régulière afin que vous puissiez rester avec cela, non?


Méfiez-vous que vous devrez peut-être manipuler des devis évasés tels que \ "



3
votes

Selon le formatage de votre chaîne d'origine, vous devriez pouvoir utiliser une expression régulière comme paramètre sur la méthode Java "Split": Cliquez ici pour un exemple .

L'exemple n'utilise pas l'expression régulière dont vous auriez besoin pour cette tâche.

Vous pouvez également utiliser Ceci alors thread comme ligne directrice (bien que ce soit en PHP) qui fait quelque chose de très proche de ce dont vous avez besoin. Manipuler que légèrement peut faire l'affaire (bien que d'avoir des devis faire partie de la production ou non peut causer des problèmes). Gardez à l'esprit que Regex est très similaire dans la plupart des langues.

EDIT : aller trop loin dans ce type de tâche peut être en avance sur les capacités de RegEx, vous devrez peut-être créer un analyseur simple.


0 commentaires

-2
votes

Avez-vous essayé de fractionnement par '=' et créez un jeton de chaque paire de la matrice résultante?


2 commentaires

Cela a le même problème que la solution .split () mentionnée dans la question.


@rajax Cette solution ne fonctionne pas, mais vous pouvez faire quelque chose comme scinder un espace, puis passer à travers chacune des chaînes fendues: si elle commence par '(en supposant qu'elle soit bien formatée), alors vous venez d'ajouter ces cordes ensemble jusqu'à ce que vous en trouver un qui se termine avec '. String Tokenziers ou une machine à états (ou à l'aide d'une pile si vous souhaitez autoriser plusieurs niveaux de guillemets de nichement en alternant les types de devis ALA Python) peut être plus efficace, mais cela peut aussi fonctionner!



1
votes

StreamTokenizer peut aider, bien que Il est plus facile de mettre en place pour rompre sur '=', car il va toujours casser au début d'une chaîne citée: xxx

sorties xxx

Si vous laissez les deux lignes qui convertissent des caractères numériques en alpha, vous obtenez d = 777.0 , ce qui pourrait vous être utile.


0 commentaires

-1
votes
java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(line, " ");
while (tokenizer.hasMoreTokens()) {
    String token = tokenizer.nextToken();
    int index = token.indexOf('=');
    String key = token.substring(0, index);
    String value = token.substring(index + 1);
}

0 commentaires

1
votes

Hypothèses:

  • Votre nom de variable ('a' dans l'affectation 'A = B') peut être de longueur 1 ou plus
  • Votre nom de variable ('A' dans l'affectation 'A = B') ne peut pas contenir le caractère spatial, tout le reste va bien.
  • La validation de votre entrée n'est pas requise (entrée supposée être dans le format A = B valide)

    Cela fonctionne bien pour moi.

    entrée: xxx

    sortie: xxx

    code: xxx


0 commentaires

0
votes

Cette solution est à la fois générale et compacte (c'est effectivement la version de la regex de la réponse de Cletus): xxx

En d'autres termes, trouvez toutes les exécutions de caractères combinant des chaînes citées ou caractères non spatiaux; Les citations imbriquées ne sont pas supportées (il n'y a pas de caractère d'échappement).


0 commentaires

3
votes
a=b
c='123 456'
d=777
e='uij yyy'

0 commentaires

0
votes
public static void main(String[] args) {
String token;
String value="";
HashMap<String, String> attributes = new HashMap<String, String>();
String line = "a=b c='123  456' d=777 e='uij yyy'";
StringTokenizer tokenizer = new StringTokenizer(line," ");
while(tokenizer.hasMoreTokens()){
        token = tokenizer.nextToken();
    value = token.contains("'") ? value + " " + token : token ;
    if(!value.contains("'") || value.endsWith("'")) {
           //Split the strings and get variables into hashmap 
           attributes.put(value.split("=")[0].trim(),value.split("=")[1]);
           value ="";
    }
}
    System.out.println(attributes);
}
output:
{d=777, a=b,  e='uij yyy',  c='123 456'}In this case continuous space will be truncated to single space in the value.
here attributed hashmap contains the values

0 commentaires

1
votes

ou, avec une regex pour la jeton et une petite machine à états qui ajoute simplement la clé / val à une carte: xxx

imprime xxx

Il effectue une vérification des erreurs de base et prend les guillemets hors des valeurs.


0 commentaires

0
votes
 import java.io.*;
 import java.util.Scanner;

 public class ScanXan {
  public static void main(String[] args) throws IOException {

    Scanner s = null;

    try {
        s = new Scanner(new BufferedReader(new FileReader("<file name>")));

        while (s.hasNext()) {
            System.out.println(s.next());
           <write for output file>
        }
    } finally {
        if (s != null) {
            s.close();
        }
    }
 }
}

1 commentaires

Oui @younghobbit Mon environnement de travail Linux (Ubuntu 15.01) codé sur sublime3.