mars
2012
Petite astuce suite à une discussion twitter avec Guillaume Laforge concernant une fonctionnalité de l’API tierce JRegex : l’incomplete matching.
Le tout à fini dans un billet de son blog anglophone : Incomplete string regex matching, et j’en profite pour faire de même en français !
Mais d’abord qu’est-ce que l’incomplete matching ? Cela permet simplement de valider partiellement une expression régulière.
Quel intérêt ? Cela permet par exemple de vérifier une saisie en cours sans générer d’erreur (par exemple lorsque la saisie n’est pas terminé).
Par exemple si l’on souhaite faire saisir à l’utilisateur une heure au format habituelle HH:MM, on utilise une expression régulière de la forme suivante : \d\d:\d\d (soit deux blocs de deux chiffres séparés par deux-points).
Une fois la saisie terminée, on peut la vérifier très facilement via notre expression régulière et la méthode matches(). Mais cette méthode renverra une valeur négative pour toutes les saisies intermédiaires, puisqu’elles ne respectent pas le pattern.
Ainsi si je veux saisir « 18:15« , les chaines intermédiaires « », « 1« , « 18« , « 18: » et « 18:1 » ne pourront pas être validées par matches() et génèreront des « faux-négatifs », empêchant toute validation à la volée…
C’est là qu’entre en jeu l’incomplete matching de JRegex. Elle propose une méthode matchesPrefix() permettant de vérifier si la chaine correspond entièrement ou partiellement à l’expression régulière, ce qui permet de ne pas générer de faux-négatif pour toutes les chaines intermédiaires, tout en permettant de détecter une saisie incorrecte au plus tôt…
Pourtant, il n’y a pas besoin de passer par une librairie externe pour faire cela, puisque c’est intégré dans l’API standard depuis Java 5.0…
Après une petite recherche dans l’API, on tombe sur une méthode hitEnd() qui peut paraitre un peu ambigüe, mais qui fournit une information toute simple : elle nous permet de déterminer si le moteur d’expression régulière a atteint la fin de la chaine.
Dans le cas d’une validation négative via matches(), il suffit donc de vérifier la valeur de retour de hitEnd() :
- En cas de réponse négative, cela signifie que le moteur a détecter une erreur dans la chaine partielle, et qu’elle est donc invalide.
- A l’inverse, si la chaine a été lu dans sa totalité, cela signifie que le moteur de regexp n’a pas trouvé d’erreur dans la chaine lu, mais qu’il lui manque des données. Bref on est alors dans le cas d’un incomplete matching !
Concrètement, cela peut s’écrire en quelques lignes :
public static boolean incompleteMatches(String regex, String input) {
return incompleteMatches(Pattern.compile(regex), input);
}
public static boolean incompleteMatches(Pattern pattern, String input) {
Matcher m = pattern.matcher(input);
return m.matches() || m.hitEnd();
}
Et voilà !
3 Commentaires + Ajouter un commentaire
Tutoriels
Discussions
- L'apparition du mot-clé const est-il prévu dans une version à venir du JDK?
- Définition exacte de @Override
- Possibilité d'accéder au type générique en runtime
- [ fuite ] memoire
- Classes, méthodes private
- jre 1.5, tomcat 6.0 et multi processeurs
- Difference de performances Unix/Windows d'un programme?
- [REFLEXION] Connaitre toutes les classes qui implémentent une interface
- Recuperation du nom des parametres
[…] JavaFX 2.x Vérification partielle avec les expressions régulières par adiGuba (27/03/2012 21:54) Petite astuce suite à une discussion twitter avec Guillaume Laforge […]
Les groupes nommés sont supportés dans Java 7 via la syntaxe (?X)
http://docs.oracle.com/javase/7/docs/api/java/util/regex/Pattern.html#gnumber
a++
Merci de me faire découvrir JRegex. Je ne connaissais pas, mais je dois avouer que cette bibliothèque à l’air très sympa.
J’apprécie aussi le support de certaines fonctionalités comme les groupes nommés qui manquent au regex java standard.