Franchement un tutoriel avec une top explication sur l'utilisation de \G, je ne me rappelle pas en avoir déjà vu.
Il y a http://www.rexegg.com/regex-anchors.html#G (en anglais). C'est un site qui est plutôt orienté PCRE à l'origine (à l'origine c'était un blog un peu fourre-tout où on pouvait trouver aussi des rythmes de percussions d'Afrique de l'ouest) avec des exemples simples, quelque cas d'utilisations, mais malheureusement rien en particulier sur comment rompre la contiguïté, et sur comment s'assurer qu'on est bien arriver au bout de ce qu'on voulait extraire.
Moi, c'est à force d'essais que j'ai fini par trouver des ruses, suivant les situations, pour que la pattern s'arrête au bon moment et pour en avoir confirmation.
Un schéma type pour trouver plusieurs cibles entre deux bornes comme ici est :
(?: \G(?!\A) partie_entre_les_cibles | amorce) (cible) (?:(?=(fin))?
Après suivant les cas, telle ou telle partie peut être enlevée. Chaque élément doit être décrit avec précision notamment la cible et la partie entre les cibles pour éviter qu'aucune d'elles ne puisse matcher la fin afin de rompre la contiguïté. C'est pour cette raison aussi que la fin est placée dans un lookahead (pour ne pas faire partie de la correspondance). Ce lookahead est lui-même placé dans un groupe optionnel pour ne pas gêner les matches successifs, et c'est seulement sur le dernier item que ce lookahead réussit. La capture de la fin sert alors de confirmation que la borne de fin à bien été atteinte et que le format est bien conforme.
Ce qui ici donne (en doublant les antislashes pour les strings Java):
1 2 3 4 5 6 7 8 9 10
| (?:\G(?!\A) , | \bObjet\[ )
# ^ ^
# | +------> amorce
# +------> truc entre les cibles
# cible
(?<key> [^]=,]*+ ) = (?<value> [^],{]*+ (?:\{[^}]*} [^],{]*)*+ )
# test sur la borne de fin
(?:(?=(?<fin>])))? |
Et si je lui passe une chaîne mal formatée comme par exemple: Objet[key1=val1,key2=key2=val2] le groupe fin n'existera jamais et donc au terme de ma boucle sur m.find(), je peux refuser l'ensemble des clefs/valeurs trouvées puisque le format n'est pas valide, voire lever une exception.
Partager