2 votes

Y a-t-il un moyen de spécifier une Regex qui ne correspond pas à une des autres ?

Disons que j'ai quelque chose comme ceci:

    pattern = new Pattern[6];
    pattern[0] = Pattern.compile("^\\s*(NOM\\:\\s*)\\s(\\w+)");
    pattern[1] = Pattern.compile("^\\s*(ÂGE\\:\\s*)\\s(\\d+)");
    pattern[2] = Pattern.compile("^\\s*(ADRESSE\\:\\s)(\\w+)");
    pattern[3] = Pattern.compile("^\\s*(DATE D'ANNIVERSAIRE\\:\\s)(\\d+)\\:(\\d+)\\:(\\d+)");        
    pattern[4] = Pattern.compile("(?=\\s*\\*)(^\\**)");
    pattern[5] = Pattern.compile("\\S+|[^\\s*.+\\s*]");

Le but du pattern 4 est de capturer les commentaires suivis de * et le pattern 5 est de capturer tout le reste que les autres patterns ne peuvent pas. Ensuite, le Matcher dp sert à vérifier si le pattern est celui attendu à partir du LookAhead en renvoyant vrai ou faux.

    public boolean lookAhead () {
        while ((line = buff.readLine()) != null) {
                 Pattern different = Pattern.compile("^[^(\\s*NOM.*)(\\s*ÂGE.*)(\\s*ADRESSE.*)(\\s*DATE D'ANNIVERSAIRE.*)]");                
                 Matcher comment = pattern[4].matcher(line);
                 Matcher diff = different.matcher(line);
                 Matcher name = pattern[0].matcher(line);
                 if (comment.find() || different.find() /*|| name.find()*/)               
                     continue;
                    Matcher dp = pattern[0].matcher(line);
                    dpla = dp.find();
                    break;
                 }
        }
        return dpla;
     }

Les commentaires sont ignorés et toutes les erreurs aléatoires comme: "feifiejfie" le seraient aussi. Cependant, si le texte est quelque chose comme "NOM 7987997 GSGSGE 456", cela devrait être considéré comme une erreur mais ce n'est pas le cas. Si name.find est décommenté, cela fonctionnera toujours, cependant, cela ne renverra jamais faux.

2voto

GhostCat Points 83269

Allons simplement pour une approche différente. Je pense qu'en essence, vous avez des chaînes d'entrée; puis vous avez une liste de différentes regex qui peuvent potentiellement contenir des correspondances qui vous intéressent. Vous faites beaucoup de correspondances dans votre code, pour finalement ne renvoyer qu'un booléen; ce qui ne semble pas utile; alors je vais vous donner une idée de comment faire les choses différemment.

 class RegexListMatcher {
   private final Map patternsById;
   private final String inputToMatchOn;

   private final String matchingId;
   private final String matchResult;

   RegexListMatcher(Map patternsById, inputToMatchOn) {
     this.patterns... = patterns
     this.input... = input

     matchingId = findMatchingId();
     if (matchingId == null) {
        matchResult = null;
     } else {
        matchResult = getMatchResult();
     }
   }

   private final String findMatchingId() {
     for (Entry entry : patternsById) {
       si l'entrée.value correspond à l'entrée donnée, retourner l'entrée.clé

     sinon retourner null
   }

   private final String getMatchResult() {
     Pattern pattern = patternsById.get(matchingId);
     retourner la valeur correspondante dans l'entrée 
   }

   public boolean hasMatch() { retour matchingID != null; }
   public String getMatchId() ...
   public String getMatchResult() ...

À utiliser comme suit:

 private final static Map RULES = new HashMap<>();
 RULES.put("NAME", Pattern.compile("^\\s*(NAME\\:\\s*)\\s(\\w+)"));
 ...

 RegexListMatcher listMatcher = new RegexListMatcher(RULES, someInputString);
 if (listMatcher.hasMatch()) { 
   l'une des règles a correspondu
 } else {
   aucune correspondance du tout
 }

Le point clé de mon implémentation : vous avez une liste de modèles potentiels; et si l'un d'entre eux correspond, vous êtes sûrement intéressé par la valeur correspondante dans votre entrée. Et surprise : si aucun des modèles ne correspond, alors vous le savez aussi. Car le RegexListMatcher peut vous le dire.

Certes, plus de code que le vôtre; mais par exemple : il n'y a pas d'accès codé en dur à un certain index de tableau du tout. De toute évidence, ce qui précède est en partie du pseudo-code, mais je suppose que cela devrait être suffisant pour vous mettre sur la bonne voie.

2voto

user3672700 Points 82

J'ai réussi à résoudre le problème aujourd'hui ! Je suis désolé si je n'ai pas bien expliqué ma question, car j'ai dû inventer des expression régulières plus simples pour essayer d'expliquer la question, peut-être ai-je manqué des points importants pour obtenir une bonne réponse. Ceci est un code très simplifié par rapport à ce que j'ai en réalité. Le problème principal était que bien que les commentaires et tout ce qui n'était pas des motifs (le motif 'error' annule tout ce qui commence par les autres motifs) seraient détectés et continueraient la boucle While, si le motif commençait par NAME: ou AGE: etc, cela signifie que ce serait différent du motif 'error', donc il ne continuerait pas la boucle, alors que cela ne devrait pas se produire car il devrait s'arrêter uniquement s'il détecte un motif valide. Donc ce que j'ai fait était ceci :

Pattern legit = Pattern.compile("^[(\\s*NAME.*)(\\s*AGE.*)(\\s*ADDRESS.*)(\\s*BIRTHDAY.*)");
Matcher leg = legit.matcher(line);

L'objectif de ce motif est de déterminer ce qui est possible au cas où le commentaire et l'erreur échouent. Et si c'est le cas, ils doivent vérifier si les valides échouent :

(leg.find() && (!name.find() && !age.find() && !addr.find() && !bd.find())))

Vous pouvez choisir le motif que vous souhaitez trouver à travers l'entier au paramètre et cela va modifier ceci :

Matcher input = pattern[a].matcher(line);
                 if (!input.find() ...)

Ainsi, tout combiné ressemblerait à ceci :

public boolean lookAhead (int a) {
        Pattern error = Pattern.compile("^[^(\\s*NAME.*)(\\s*AGE.*)(\\s*ADDRESS.*)(\\s*BIRTHDAY.*)]");
        Pattern legit = Pattern.compile("^[(\\s*NAME.*)(\\s*AGE.*)(\\s*ADDRESS.*)(\\s*BIRTHDAY.*)");
        while ((line = buff.readLine()) != null) {                                
                 Matcher comment = pattern[4].matcher(line);
                 Matcher err = error.matcher(line);
                 Matcher leg = legit.matcher(line);
                 Matcher name = pattern[0].matcher(line);
                 Matcher age = pattern[1].matcher(line);
                 Matcher addr = pattern[2].matcher(line);
                 Matcher bd = pattern[3].matcher(line);
                 Matcher input = pattern[a].matcher(line);
                 if (!input.find() && (comment.find() || err.find() || (leg.find() && (!name.find() && !age.find() && !addr.find() && !bd.find())))               
                     continue;
                    Matcher dp = pattern[a].matcher(line);
                    dpla = dp.find();
                    break;
                 }
        }
        return dpla;
     }

Fonctionne exactement comme je le voulais :D

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X