Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1594 connectés 

  FORUM HardWare.fr
  Programmation
  Divers

  Aide REGEXP pourtant simple

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Aide REGEXP pourtant simple

n°2399024
jeromax
Posté le 27-10-2021 à 11:42:56  profilanswer
 

Hello,
J'ai écrit une regexp, elle fonctionne... presque
Règle : ne doit pas commencer par un tiret et ne doit pas se terminer par un tiret
 
Elle est plus complexe que ça, en réalité il y a une liste de caractères interdits en début de chaine et une autre liste de caractères interdits en fin de chaines mais le problème reste le même.
Cette regexp fonctionne correctement SAUF s'il n'y a qu'un seul caractère.  

Code :
  1. ^[^-].*[^-]$


Résultats:

Code :
  1. a => ko (devrait être ok !)
  2. a- => ko (résultat attendu)
  3. -a- => ko (résultat attendu)
  4. - => ko (résultat attendu)
  5. aa => ok (résultat attendu)
  6. azdeazdadad-azeaze => ok (résultat attendu)


Où est le problème? normalement le point signifie n'importe quel caractère donc suivi par une étoile, cela devrait matcher s'il n'y a qu'1 seul caractère non...?

mood
Publicité
Posté le 27-10-2021 à 11:42:56  profilanswer
 

n°2399036
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 27-10-2021 à 12:34:14  profilanswer
 

Le second "[^-]" rend la saisie d'un caractère autre que "-" obligatoire. Par conséquent, entre ça et le ".*" précédent, tu dois saisir au minimum 2 caractères pour que ta regex fonctionne.

 

Tu peux donc virer la fin de ta regex qui devient juste :

 
Code :
  1. ^[^-]*$


Message édité par Harkonnen le 27-10-2021 à 12:36:03

---------------
J'ai un string dans l'array (Paris Hilton)
n°2399041
jeromax
Posté le 27-10-2021 à 13:09:08  profilanswer
 

Merci de ta réponse mais cela ne fonctionne pas
https://regex101.com/r/ZpXmGD/1
la première ligne doit passer ainsi que les 4 dernières


Message édité par jeromax le 27-10-2021 à 13:12:31
n°2399050
mechkurt
Posté le 27-10-2021 à 14:33:15  profilanswer
 

Je ne sais pas si c'est pertinent mais y'a des fonctions dans le plupart des langages bcps moins couteuse en temps machine que de faire une regex.
 
Pourquoi ne pas comparer la longueur de ta chaine avant et après un trim des tiret par exemple, ou tester le 1er et le dernier caractère, car là tu t'embarques dans une regex alors que résultat vide est bon, ça me semble un peu overkill...


---------------
D3
n°2399051
jeromax
Posté le 27-10-2021 à 14:35:18  profilanswer
 

C'est ce que j'ai fait oui :D  
j'ai gardé ma regexp et ajouté une condition au cas où il n'y a qu'un seul caractere. D'ailleurs c'est probablement plus maintenable qu'une regexp de 12km de long...

n°2399160
kisscoolz
Posté le 28-10-2021 à 12:50:00  profilanswer
 

jeromax a écrit :


Règle : ne doit pas commencer par un tiret et ne doit pas se terminer par un tiret
...

Code :
  1. ^[^-].*[^-]$




 
Peut être avec quelque chose comme ca ?
 

Code :
  1. (^[^-].*|.*[^-]$)


 
A paufiner un peu surement parce que j'ai un doute sur la syntaxe exacte mais l'idée est là.


Message édité par kisscoolz le 28-10-2021 à 12:50:36

---------------
http://lacabanedeladmin.trickip.net/
n°2399211
MaybeEijOr​Not
but someone at least
Posté le 28-10-2021 à 20:39:45  profilanswer
 

Code :
  1. ^[^-]?[^-]*[^-]?$


Et cela ?


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2399234
TotalRecal​l
Posté le 29-10-2021 à 09:48:05  profilanswer
 

Marche pas, ça ne matche pas azdeazdadad-azeaze :D

 

La question est mal posée côté exemples mais je pense qu'il veut matcher :

aa
a
azdeazdadad-azeaze

 

Et rejeter :

a-
-a-
-

 

A confirmer.

 

C'est vrai que ça semble trivial mais quand tu testes ben ça l'est pas :o
Ou alors il faut tricher un peu et mettre du | à défaut d'arriver à exprimer le truc en un coup.

Message cité 2 fois
Message édité par TotalRecall le 29-10-2021 à 09:50:29

---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
n°2399236
MaybeEijOr​Not
but someone at least
Posté le 29-10-2021 à 10:02:52  profilanswer
 

TotalRecall a écrit :

Marche pas, ça ne matche pas azdeazdadad-azeaze :D
 
La question est mal posée côté exemples mais je pense qu'il veut matcher :

aa
a
azdeazdadad-azeaze


 
Et rejeter :

a-
-a-
-


 
A confirmer.


Non, non c'est bien ce que j'avais compris aussi, j'ai juste oublié de prendre en compte sa dernière ligne, je me suis focalisé sur pas de tiret au début, pas de tiret à la fin et possibilité d'un seul caractère sans penser au cas où le tiret est au milieu.


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2399238
jeromax
Posté le 29-10-2021 à 11:13:56  profilanswer
 

TotalRecall a écrit :

Marche pas, ça ne matche pas azdeazdadad-azeaze :D
 
La question est mal posée côté exemples mais je pense qu'il veut matcher :

aa
a
azdeazdadad-azeaze


 
Et rejeter :

a-
-a-
-


 
A confirmer.
 
C'est vrai que ça semble trivial mais quand tu testes ben ça l'est pas :o
Ou alors il faut tricher un peu et mettre du | à défaut d'arriver à exprimer le truc en un coup.


Oui c'est ça :-)

mood
Publicité
Posté le 29-10-2021 à 11:13:56  profilanswer
 

n°2399240
reroll
Posté le 29-10-2021 à 11:41:59  profilanswer
 

J'aurai plutot vu :
 
 

Code :
  1. ^[^-]?.*[^-]$


 
D'ailleurs dans le lien vers regex101 que tu as mis, le retour à la ligne de la ligne 5 (celle ou il y a rien) fou la merde, si tu l'enleve ma regex pass bien, si tu la remets ca remerde. Je ne sais pas si c'est un bug du site.
 
Pour être plus précis, des que tu fais un retour à la ligne sans rien, la ligne du dessus se met à matcher sans raison.


Message édité par reroll le 29-10-2021 à 11:48:17
n°2399253
TotalRecal​l
Posté le 29-10-2021 à 14:08:04  profilanswer
 

Ah ouais bien vu, c'est assez déroutant.
 
Par contre ta regex matche aussi :
-a
Dont je ne sais pas si c'est admissible ou pas vu que le 1er post n'en dit rien, comme je disais le jeu d'exemple est insuffisant.


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
n°2399255
reroll
Posté le 29-10-2021 à 14:15:29  profilanswer
 

Bien vu pour le -a, vu que c'est pas dans le poste initial, je n'ai pas testé.

n°2399264
jeromax
Posté le 29-10-2021 à 14:35:12  profilanswer
 

La règle est : ne doit pas commencer par un tiret et ne doit pas se terminer par un tiret (quelque soit le nombre de caractères)
Merci beaucoup de vous pencher sur le sujet!

n°2399266
TotalRecal​l
Posté le 29-10-2021 à 14:46:33  profilanswer
 

Sauf que même comme ça c'est ambigu, d'où la nécessité de fournir un vrai jeu de validation. Un truc formel qui ne laisse aucune place à l'interprétation, et directement copiable dans un outil genre regex101.

 

Parce qu'en français et en informatique les opérateurs logiques ont une fâcheuse tendance à ne pas avoir le même sens.

 

"ne doit pas commencer par un tiret et ne doit pas se terminer par un tiret" ça peut vouloir dire qu'on accepte TOUT, sauf ce qui commence et finit en même temps par un tiret.
Mais également qu'on accepte ce qui ne commence par par un tiret, mais aussi ce qui ne finit par par un tiret.
Edit : en me relisant je pense que j'ai écrit une connerie mais vous saisissez le propos [:ddr555]

 

Et on ne sait pas si c'est un devoir scolaire (auquel cas on va lever un peu le pied :o) ou un truc qui sert un besoin réel...


Message édité par TotalRecall le 29-10-2021 à 14:49:23

---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
n°2399269
jeromax
Posté le 29-10-2021 à 15:36:53  profilanswer
 

Effectivement, c'est mieux comme ça : ne doit pas commencer par un tiret OU ne doit pas se terminer par un tiret (tout autre caractère est autorisé)
-aaa ne doit pas passer
aaa- ne doit pas passer
-aaa- ne doit pas passer
aaa doit passer
a doit passer
aaa-a doit passer
aaa-a-aa doit passer
 
Pour le moment j'ai utilisé ma regex du début et testé en plus que le mot n'est pas un tiret lorsque sa longueur est 1  
Et c'est un vrai besoin d'entreprise :jap:  

n°2399272
reroll
Posté le 29-10-2021 à 15:46:23  profilanswer
 

Je vais être encore un peu plus pointilleux dans l'énoncé, mais j'imagine que c'est "ne doit pas commencer ou terminer par UN OU PLUSIEURS tiret" donc en gros
 
--aa / aa-- et --aa-- ne doivent pas matcher non plus ?
 
Ou en plus français : Le premier et le dernier caractère de la chaîne ne peuvent pas être un tiret "-".


Message édité par reroll le 29-10-2021 à 15:47:49
n°2399274
jeromax
Posté le 29-10-2021 à 15:48:45  profilanswer
 

oui, tant qu'il y a un tiret au début ou à la fin, cela ne doit pas matcher

n°2399277
reroll
Posté le 29-10-2021 à 16:08:22  profilanswer
 

Celui semble être le bon :  
 
v1

Code :
  1. ^(?![-]).*[^-]$


 
v2

Code :
  1. ^(?![-\s]).*[^-]$


 
Celui du v2 exclu les whitespaces en début de chaine, donc ca exclu les ligne vides et les chaines commençant avec un espace ou une tabulation.
 
Pour être sur je l'ai testé sur tout ça .
 
-a
--a
-aa
aa-
--aa
aa--
aa--aa
aa--aa--
--aa--aa
--aa--aa--
--aa--
aa--aa--aa
 
 
Et je confirme le bug sur le site regex101 du coup je suis passé par https://regexr.com/ qui semble plus fiable.


Message édité par reroll le 29-10-2021 à 16:31:28
n°2399279
jeromax
Posté le 29-10-2021 à 16:31:49  profilanswer
 

Joli ! !
Cela semble fonctionner en effet.
Merci beaucoup  :jap:

n°2399280
TotalRecal​l
Posté le 29-10-2021 à 16:55:56  profilanswer
 

Pas mal le negative lookahead de ce qu'on ne veut pas, même si comme disait mechkurt c'est pas dément tout ça niveau perfs :D


---------------
Réalisation amplis classe D / T      Topic .Net - C# @ Prog
n°2399291
reroll
Posté le 29-10-2021 à 18:05:53  profilanswer
 

Clairement, je n'utiliserai les regex que pour des pattern complexes qui nécessiteraient trop de lignes de code pour un équivalent avec des opérations sur les String.

n°2399317
gilou
Modérateur
Modzilla
Posté le 30-10-2021 à 01:03:52  profilanswer
 

jeromax a écrit :

Hello,
J'ai écrit une regexp, elle fonctionne... presque
Règle : ne doit pas commencer par un tiret et ne doit pas se terminer par un tiret
 
Elle est plus complexe que ça, en réalité il y a une liste de caractères interdits en début de chaine et une autre liste de caractères interdits en fin de chaines mais le problème reste le même.
Cette regexp fonctionne correctement SAUF s'il n'y a qu'un seul caractère.  

Code :
  1. ^[^-].*[^-]$


Résultats:

Code :
  1. a => ko (devrait être ok !)
  2. a- => ko (résultat attendu)
  3. -a- => ko (résultat attendu)
  4. - => ko (résultat attendu)
  5. aa => ok (résultat attendu)
  6. azdeazdadad-azeaze => ok (résultat attendu)


Où est le problème? normalement le point signifie n'importe quel caractère donc suivi par une étoile, cela devrait matcher s'il n'y a qu'1 seul caractère non...?


Le problème est évident :
Chacun des [^-] de ton expression vaut un caractère. Ton expression doit donc avoir au moins deux caractères.
La corriger est donc simplissime :
^[^-](.*[^-])?$
ou mieux, en évitant de faire un capturing group inutile
^[^-](?:.*[^-])?$
Et pas besoin de lookahead pour cela
 
Par contre, si tu as deux listes différentes pour le début et la fin (au vu de ton post) ça complique un poil les choses :
si abc représente la liste des caractères interdits au début et xyz celle de ceux interdits à la fin, il faudra faire ainsi :  
^[^abcxyz]|[^abc].*[^xyz]$ avec éventuellement simplification du premier terme s'il y a des caractères interdits communs a la liste du début et celle de fin.
^[^abcxyz]$|^[^abc].*[^xyz]$ avec éventuellement simplification du premier terme s'il y a des caractères interdits communs a la liste du début et celle de fin.
 
A+,


Message édité par gilou le 02-11-2021 à 11:16:16

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2399322
MaybeEijOr​Not
but someone at least
Posté le 30-10-2021 à 09:55:10  profilanswer
 

Cela rejoint un peu Gilou mais en plus clair je pense, il suffit de supposer les deux cas :
- 1 seul caractère
- plusieurs caractères

 

Dans cet exemple, ça ne doit pas commencer par un "0" ou finir par un "a" (je nettoie les retours chariots pour le multi-ligne) :

 

^[^a0\r\n]$|^[^0\r\n]+[^a\r\n]+$

 

Ainsi en première partie (^[^a0\r\n]$) on retrouve le cas d'un seul caractère et donc l'union de tous les caractères par lesquels on ne veut pas que ça commence ou finisse ("0" et "a", ainsi que les retours chariots).
Dans la seconde partie (^[^0\r\n]+[^a\r\n]+$) on demande que ça ne commence par au moins un des caractères interdits en début ("0" ainsi que les retours chariots : ^[^0\r\n]+) et que ça ne finisse pas par au moins un des caractères interdits en fin ("a" ainsi que les retours chariots : [^a\r\n]+$).

 

https://regex101.com/r/soW12S/1

  

EDIT : cela rejoint complètement l'idée de Gilou en fait, simplement il y avait quelques corrections à apporter, dans la première partie il faut bien spécifier le $ et après dans la seconde partie pas besoin de spécifier "possiblement n'importe quel caractère" en utilisant le bons quantifiers sur les deux autres sous-groupes.


Message édité par MaybeEijOrNot le 30-10-2021 à 10:03:41

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
n°2399508
gilou
Modérateur
Modzilla
Posté le 02-11-2021 à 10:57:11  profilanswer
 

Tu as raison, quand j'ai écrit ^[^abcxyz]|[^abc].*[^xyz]$ j'avais bien sur en tête ^(?:[^abcxyz]|[^abc].*[^xyz])$  
Soit ^[^abcxyz]$|^[^abc].*[^xyz]$ si on n'a pas envie d’écrire de groupe, même non capturant
Mais effectivement, je ne connais pas les règles de précédence pour ^ et $ et ça faussait peut-être l'expression initiale.
EDIT : ^ et $ sont au 3e niveau, tandis que | est au 4e et dernier (par construction, | a toujours le plus bas niveau, plus bas que pour tout autre élément d'une regexp, bref, c'est le dissociateur ultime), donc ^a|b$ c'est pas ^a$|^b$ et mon expression initiale était fausse.
A+,


Message édité par gilou le 02-11-2021 à 11:17:30

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
n°2399927
jeromax
Posté le 08-11-2021 à 10:24:14  profilanswer
 

Rhooo merci à tous pour vos messages.
j'utilise maintenant ^(?![-\\s\']).*[^-\\s]$ et elle fonctionne parfaitement pour mes règles de gestion (et donc mes cas JUnit)

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Divers

  Aide REGEXP pourtant simple

 

Sujets relatifs
[Algorithme][Aide] Partons de vrai et bien.../...Aide niveau programmation débutant
[Résolu] Pb de regexp avec MysqlBesoin d'aide pour la conception de mon MCD
[réglé] utiliser GTK(4) en Perl? Autre possibilité pour GUI simple?aide pour script microsoft visual basic
Aide Batch copy + rename (plusieurs dossiers a traiter en même temps)aide écriture code c++ recherche et cumul de nombres
Besoin d'aide pour créer un site B2B[Résolu] aide pour manipulation fichier texte en powershell
Plus de sujets relatifs à : Aide REGEXP pourtant simple


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR