Page 1 sur 1
Question expression régulieres
Publié : sam. 26/août/2023 23:34
par cage
Bonsoir a tous,
Encore un domaine où j'ai beaucoup de lacunes.
Dans la lecture d'un fichier ligne a ligne, je voudrais pouvoir détecter si la ligne contient certains motifs tels que:
une suite de 3 # --> ###
une suite de 3 * --> ***
une suite de 3 + --> +++
une suite de 3 - --> ---
une suite de 3 = --> ===
une suite égale a - -
J'ai écris cette expression régulière qui fais bien le travail, mais je ne suis pas sur que ce soit la meilleure façon de faire.
Une âme charitable pourrait-elle me dire si j'ai bon ou s'il y a une meilleure façon de faire.
Merci d'avance.
cage
Voici la solution que j'ai trouvé dans ce bout de code
Code : Tout sélectionner
EnableExplicit
Define NewMap chaine.s(),N,texte$
chaine("1") = "Chaine1 : Tester si 3 *** dans la chaine."
chaine("2") = "Chaine2 : Tester si 3 ### dans la chaine."
chaine("3") = "Chaine3 : Tester si 3 === dans la chaine."
chaine("4") = "Chaine4 : Tester si 3 +++ dans la chaine."
chaine("5") = "Chaine5 : Tester si 3 --- dans la chaine."
chaine("6") = "Chaine6 : Tester si 3 - - dans la chaine."
chaine("7") = "Chaine7 : Cette chaine"
Define regex=CreateRegularExpression(#PB_Any, "([*]{3}|[#]{3}|[=]{3}|[-]{3}|[+]{3}|- -)")
For N=1 To 7
texte$=chaine(Str(N))
If regex
If ExamineRegularExpression(regex, texte$)
If NextRegularExpressionMatch(regex)
Debug texte$
Else
Debug chaine(Str(N))+" ne contient aucun des motifs."
EndIf
EndIf
Else
EndIf
Next
FreeRegularExpression(regex)
Re: Question expression régulieres
Publié : dim. 27/août/2023 17:26
par boddhi
Ton code a l'air de satisfaire ton attente mais sans exemples précis de chaînes que tu as à traiter, il est difficile de dire s'il peut être fait mieux.
La contrainte peut-elle être trouvée à un endroit qui n'est pas celui attendu ?
Doit-il y avoir une seule contrainte par chaîne ?
Re: Question expression régulieres
Publié : dim. 27/août/2023 18:05
par cage
Il n'y a aucune contrainte particulière a la recherche.
Ça doit 'matcher' si au moins un des motifs "###", "***", "===",... est contenu dans la chaine.
Le motif est une chaine d'au mois 3 caractères, ce qui veut dire que "===" ou "==============" ou "=== ###" "matchent".
Ma question porte plutôt sur la façon d'écrire un motif, par exemple quel motif décrit le mieux 3 caractères "=" qui se suivent.
Pour moi, [=]{3} signifie la répétition de 3 caractères "="
Pour moi, [.]{3} signifie la répétition de 3 caractères "." tout en enlevant la signification du point "." qui peut représenter n'importe quel caractère.
Il y-a-t-il une autre façon plus efficace d'écrire ce motif.
cage
Re: Question expression régulieres
Publié : dim. 27/août/2023 20:18
par Marc56
Bonsoir,
ou ça:
Seul * et + ont besoin d'\
Mais bon, pour du texte fixe, autant utiliser FindString()

Re: Question expression régulieres
Publié : dim. 27/août/2023 20:30
par boddhi
Tout comme dans d'autres langages, certains caractères/symboles/signes sont dits 'spéciaux' et ont une signification/fonction précise. Le '.' en regex en fait partie comme tu le sais.
Donc, pour pouvoir les considérer comme caractères normaux, il te faut recourir au caractère (dit d'échappement) '\' .
Ainsi, si tu veux qu'un point soit reconnu dans un regex, tu devras écrire '\.' donc '\.{3}' recherchera '...' dans ta chaîne de caractères (Bien-sûr ne pas tenir compte des apostrophes présents dans mes exemples

)
De même, si tu recherches le caractère '\' dans une chaîne, tu devras l'annoter '\\' dans ta regex.
Edit : @Marc, tu as rédigé ta réponse plus rapidement que moi, du coup certains éléments de la mienne sont redondants

Re: Question expression régulieres
Publié : dim. 27/août/2023 20:42
par boddhi
@Marc,
Marc56 a écrit :
Mais bon, pour du texte fixe, autant utiliser FindString()
Question technique : Selon toi, quand tu as une dizaine de FindString() à effectuer pour rechercher une dizaine de chaînes de caractères à la suite, un peu comme dans le cas de
cage, pour des chaînes très longues, quelle est la solution la plus rapide : FindString() ou une Regex ? La question vaut aussi pour ReplaceString()...
Re: Question expression régulieres
Publié : dim. 27/août/2023 23:00
par cage
Bonsoir,
Tiré de la doc, je site:
CreateRegularExpression()
Syntax
Result = CreateRegularExpression(#RegularExpression, Pattern$ [, Flags])
Description
Create a new regular expression using the specified pattern.
Parameters
#RegularExpression A number to identify the new regular expression. #PB_Any can be used to auto-generate this number.
Pattern$ The regular expression which will be applied to the string to match, extract or replace.
Flags (optional) It can be a combination of the following values:
#PB_RegularExpression_DotAll : '.' matches anything including newlines.
#PB_RegularExpression_Extended : whitespace and '#' comments will be ignored.
#PB_RegularExpression_MultiLine : '^' and '$' match newlines within data.
#PB_RegularExpression_AnyNewLine: recognize 'CR', 'LF', and 'CRLF' as newline sequences.
#PB_RegularExpression_NoCase : comparison and matching will be case-insensitive
Donc, dans un regex PB, inutile de protéger '.' par '\."
@Marc56,
Mais bon, pour du texte fixe, autant utiliser FindString()
Dans mon cas, non. J'ai testé avec FindString() et regex, il n'y a pas photo.
Le traitement par regex est beaucoup plus rapide et simple a écrire.
Un exemple de ce que je faisais avec FindString() et maintenant avec un regex
Code : Tout sélectionner
If FindString(entry$,"---") Or
FindString(entry$,"***") Or
FindString(entry$,"===") Or
FindString(entry$,"+++") Or
FindString(entry$,"###") Or
FindString(entry$,"- -") Or
FindString(entry$,"...")
J'ai testé avec
ou ça:
"(?:\*|#|=|\+|-){3}|- -")
Plain text
Seul * et + ont besoin d'\
C'est Ok pour moi, écriture plus condensée.
Je commence a fatiguer, donc je crois que je vais en rester là pour ce soir.
Bonne nuit a tous,
cage
Re: Question expression régulieres
Publié : lun. 28/août/2023 7:15
par boddhi
cage a écrit :
Donc, dans un regex PB, inutile de protéger '.' par '\."
En es-tu si certain ?
Code : Tout sélectionner
RegEx=CreateRegularExpression(0,".",#PB_RegularExpression_DotAll)
Debug MatchRegularExpression(0,"C:\Fichier") ; Il n'y a pas de point et pourtant il y a bien un retour positif !!!
Debug MatchRegularExpression(0,"C:\Fichier.txt")
FreeRegularExpression(0)
RegEx=CreateRegularExpression(0,"\.",#PB_RegularExpression_DotAll)
Debug MatchRegularExpression(0,"C:\Fichier")
Debug MatchRegularExpression(0,"C:\Fichier.txt")
EDIT : Ajout du code suivant :
Code : Tout sélectionner
RegEx=CreateRegularExpression(0,".{3}",#PB_RegularExpression_DotAll)
Debug MatchRegularExpression(0,"C:\Fichier..")
Debug MatchRegularExpression(0,"C:\Fichier.txt")
Debug MatchRegularExpression(0,"C:\Fichier...txt")
FreeRegularExpression(0)
RegEx=CreateRegularExpression(0,"\.{3}",#PB_RegularExpression_DotAll)
Debug MatchRegularExpression(0,"C:\Fichier")
Debug MatchRegularExpression(0,"C:\Fichier.txt")
Debug MatchRegularExpression(0,"C:\Fichier...txt")
Re: Question expression régulieres
Publié : lun. 28/août/2023 7:29
par Marc56
Le point (dot) en langage Expressions Régulière signifie tous les caractères SAUF le saut de ligne.
Raison historique des anciens programmes qui analysaient ligne par ligne.
Explication ici
Donc on a un paramètre pour indiquer si on veut que le saut de ligne (CR, LF (\n \r)) soit considéré comme n'importe quel caractère. (et le saut de ligne est différent Windows, Linux, Mac)
Utiliser les expression régulières ou la recherche en texte ne doit pas changer grand chose sur des petits fichiers. On n'est pas à quelques millisecondes près, donc on privilégie la lisibilité pour la facilité de maintenance. Si on a des milliers, millions de lignes, on teste avant.
Les regex sont intéressantes voir plus simples quand on a des données variables (ex: numéros de téléphone, adresses mails) ou des données balisées pas toujours collées (ex: Facture: <des caractères> des chiffres)
Re: Question expression régulieres
Publié : lun. 28/août/2023 11:34
par cage
Bonjour,
@boddhi,
J'ai repris ton code et je l'ai modifié, histoire d'y voir plus clair.
Code : Tout sélectionner
Declare Tester(RegEx,t$)
OpenConsole()
ConsoleColor(15,0)
RegEx=CreateRegularExpression(#PB_Any,".{3}")
Tester(RegEx,"C:\Fichier..")
Tester(RegEx,"C:\Fichier.txt")
Tester(RegEx,"C:\Fichier...txt")
FreeRegularExpression(RegEx)
PrintN(RSet("",30,"-"))
RegEx=CreateRegularExpression(#PB_Any,"[.]{3}")
Tester(RegEx,"C:\Fichier..")
Tester(RegEx,"C:\Fichier.txt")
Tester(RegEx,"C:\Fichier...txt")
FreeRegularExpression(RegEx)
PrintN(RSet("",30,"-"))
RegEx=CreateRegularExpression(#PB_Any,"\.{3}")
Tester(RegEx,"C:\Fichier..")
Tester(RegEx,"C:\Fichier.txt")
Tester(RegEx,"C:\Fichier...txt")
FreeRegularExpression(RegEx)
PrintN(RSet("",30,"-"))
Input()
CloseConsole()
Procedure Tester(RegEx,t$)
result$="faux"
If RegEx
result=MatchRegularExpression(RegEx,t$)
If result:result$="trouvé":EndIf
If ExamineRegularExpression(RegEx, t$)
If NextRegularExpressionMatch(RegEx)
match$=RegularExpressionMatchString(RegEx)
PrintN("résultat sur "+t$+ " : "+result$+" "+match$)
Else
PrintN("résultat : "+result$)
EndIf
EndIf
EndIf
EndProcedure
Le flag
#PB_RegularExpression_DotAll ne semble pas fonctionner comme attendu.
Conclusion:
L'expression "
.{3}" trouve tout et n'importe quoi avec ou sans le flag
L'expression "
\.{3}" trouve bien trois points qui se suivent
L'expression "
[.]{3}" trouve bien trois points qui se suivent
Voici le résultat obtenu en exécutant le code
Code : Tout sélectionner
résultat sur C:\Fichier.. : trouvé C:\
résultat sur C:\Fichier.txt : trouvé C:\
résultat sur C:\Fichier...txt : trouvé C:\
------------------------------
résultat : faux
résultat : faux
résultat sur C:\Fichier...txt : trouvé ...
------------------------------
résultat : faux
résultat : faux
résultat sur C:\Fichier...txt : trouvé ...
------------------------------
Merci a vous deux (boddhi et Marc56) pour vos informations très précieuses.
cage