01-12-2015 09:07 AM - modifié 01-12-2015 09:30 AM
Bonjour à tous,
soit 4 caractères : a b c d
Je cherche une expression régulière qui me détecterait :
une suite de 1 à 4 caractères ... caractères uniquement compris dans "abcd" ... MAIS ... chaque caractère ne peut être présent qu'une seule fois
et c'est cette dernière condition qui me pose problème (je ne sais même pas si cela est réalisable avec une expression régulière)
exemple "ok"
a : ok
ca : ok
cbd : ok
abcd : ok
exemple "non" (car un des caractères est repris plus d'une fois)
aa : non
cca : non
cbbd : non
abbc :non
addd:non
un pro des expressions régulières aurait-il une idée ?
merci.
Résolu ! Accéder à la solution.
01-12-2015 10:19 AM - modifié 01-12-2015 10:40 AM
Seulement pour 4 caractères ? ou N caractères ? 🙂
Quid de "bada" = NOK selon ce que tu dis mais pas présent dans tes mauvais exemples (dupliqués mais non-consécutifs)
Eric M. - Senior Software Engineer
Certified LabVIEW Architect - Certified LabVIEW Embedded Systems Developer - Certified LabWindows™/CVI Developer
Neosoft Technologies inc.
01-12-2015 11:02 AM - modifié 01-12-2015 11:08 AM
Bon, si caractère qui se répète (consécutifs), (\w)(\1) fonctionne bien.
Si caractère dupliqué peu importe sa position, je n'ai pas encore trouvé la clé magique (presque). Mais vu la tête de l'expression la plus fonctionnelle que j'ai trouvé, je doute très fort de ses performances. Ne pas oublier que les PCRE sont gourmandes en ressources.
Du coup, de la bonne vieille manipulation d'octets...
C'est pas très élégant mais ça fait le job.
EDIT :
Magic RegEx : (\w).*(\1)
Eric M. - Senior Software Engineer
Certified LabVIEW Architect - Certified LabVIEW Embedded Systems Developer - Certified LabWindows™/CVI Developer
Neosoft Technologies inc.
le 01-12-2015 02:15 PM
salut Eric,
merci d'avoir pris le temps de ... sympa !
oui ... pas 2 fois le même ... consécutifs ou pas.
(il ne peut y avoir qu'une et une seule occurence par caractère)
ton code ....
oui, avec "du code" ... c'est ce que je fais pour le moment.
la condition 1 et 2 via une expression regex ... et la 3eme avec du code.
mais je cherche une expression qui fasse "tout' !
hummm ..... (\w).*(\1) ...... je "sens" un truc intéressant ici.
Ceci dit, dans ton code (et dans ton expression régulière), je ne vois pas ou se trouve les caractères "abcd", ni ou se trouve la condition de "1 à 4" caractères.
PS:
"je doute très fort de ses performances. Ne pas oublier que les PCRE sont gourmandes en ressources."
ce code ne se trouve pas dans un boucle ... il s'exécute une seule fois, à la demande, depuis le FP.
le 01-12-2015 07:02 PM
J'ai simplifié ...
Je recherche une chaine de 4 caractères, tous compris dans [abcd]
mais pour chaque caractère, je ne veux que une et une seule occurence.
exemples OK : abcd , badc , etc
exemples NOK : cdbc , bbcd , etc
Perso, je m'y suis cassé les dents, je n'ai pas trouvé (je reste cependant persuadé que cela est possible ... il faut utiliser la récursivité dans l'expression)
s'il existe sur ce forum un "fou furieux" de regex ... le défi est lancé
le 01-13-2015 02:18 AM
Si abcd sont les seuls caractères supportés... : ([a-d])[a-d]{0,3}(\1)
Il faut simplement s'assurer avant que la longueur de la chaine d'entrée soit de 4. Après, les PCRE retournent dès qu'elles trouvent un motif, donc si le dupliqué est le 2ème ou 3ème caractère, elles ne s'intéresseront pas à savoir s'il existe d'autres caractères après.
Conséquence : "bbdx" sera successful.
Seule solution pour moi : rajouter un match pattern avant la PCRE pour s'assurer qu'on n'a que 4 caractères qui sont des abcd
Hope this helps
Eric M. - Senior Software Engineer
Certified LabVIEW Architect - Certified LabVIEW Embedded Systems Developer - Certified LabWindows™/CVI Developer
Neosoft Technologies inc.
le 01-13-2015 03:37 AM
Eric ...
ton code proposé en snippet verrouille sur "bbbb", "caac" ... (par contre il ne détecte pas "abcd")
Ceci dit ... ce résultat est normal avec comme regex "([a-d])[a-d]{0,3}(\1)"
ton 1er terme ([a-d]) et ton dernier terme (\1) ... force d'office le résultat à avoir 2 lettres identiques. (la 1ere et la dernière)
mais c'est tout le contraire de ce que je recherche
ou alors je n'arrive pas à me faire comprendre (toujours possible aussi)
conditions:
4 lettres, toutes comprises dans <a,b,c,d> ... mais ... une seule occurence maximum par lettre
c.a.d. ... toutes les combinaisons possibles entre <a,b,c,d>,
mais à chaque fois, avec 1 seul "a", 1 seul "b", 1 seul "c" et 1 seul "d".
abcd
abdc
acbd
acdb
adbc
adcb
....
il faut utiliser la capacité d'une regex à faire du backtraking ...
et l'obliger, à chaque fois qu'elle ajoute une lettre, de vérifier si cette lettre est déjà reprise (ou pas) dans la séquence en cours.
ça, c'est l'idée ... (mais ma main à couper que la solution est dans ce sens là)
le 01-13-2015 03:51 AM
So what. Le code que j'ai posté est juste fait en logique négative (il est plus facile de trouver des dupliqués que des uniques) : il ne retourne pas (valeur -1) quand il n'y a pas de dupliqué. Après, je n'ai pas été très intelligent sur les valeurs d'offset sur les conditions de longueur et de type de lettre contenue (mettre -3 et -2 par exemple ?)
Pour moi tout fonctionne. Ah, si il faut changer le Search Pattern de la première fonction par [a-d][a-d][a-d][a-d] (pas le choix, les accolades ne sont pas supportées pour cette fonction) parce qu'avant, "xyab" était une entrée valide...
Eric M. - Senior Software Engineer
Certified LabVIEW Architect - Certified LabVIEW Embedded Systems Developer - Certified LabWindows™/CVI Developer
Neosoft Technologies inc.
le 01-13-2015 05:17 AM
logique négative ... ok ...
" .... je n'ai pas été très intelligent ... "
mais non ... ... tu as suffisamment d'antécédents "pointus" à ton actif pour que cette phrase ne s'applique pas en ce qui te concerne.
pas trop le "temps de", peut-être (histoire de dire quelque chose) .... mais pas assez intelligent ... je n'y crois pas une seconde !
ok, problème résolu.
Bonne journée.
le 01-14-2015 05:18 AM
voila une expression qui fait le travail ... pour 4 caractères "KQkq"
([KQkq])(?!\1)(?=[KQkq])(.)(?!\1)(?!\2)(?=[KQkq])(.)(?!\1)(?!\2)(?!\3)(?=[KQkq]).
elle lock uniquement sur une série de 4 caractères compris dans [KQkq], avec au maximum une seule occurence par caractère.
bien dommage que l'on ne puisse "voir" par regex si un caractère est repris (ou pas) dans un groupe capturé.
l'expresson (?=[\1]) ou (?![\1]) n'étant pas reconnue (il n'est pas possible de faire référence à un groupe capturé entre 2 "crochets")
autrement dit, impossible de transformer un groupe capturé en "classe de caractères".
... très dommage, car si cela était possible l'expression serait beaucoup plus courte par utilisation des capacités de backtracking d'une regex.
et l'on pourrait alors généraliser à "N".