Page 1 sur 2

Caractère non pris en charge par l'EDI

Publié : jeu. 06/déc./2012 16:44
par gibet_b
Bonjour à tous,

Comme je l'ai dit dans un autre sujet, je me frotte à PureBasic, en transposant une petite application que j'ai créé pour aider ma femme à faire des textes à trous.

Je parcours le texte soumis caractère par caractère, et pour détecter s'il s'agit d'un caractère de ponctuation, voilà comment je faisais sous RealBasic :

1/ Je déclarais une constante contenant tous les signes de ponctuation (ou en tout cas ceux qui m'intéressent) :

Code : Tout sélectionner

Const PONCTUATION = ".,;?!()"“”«»':-—–’"
2/ Je vérifiais si le caractère en cours figurait dans la contante pour savoir si c'était un signe de ponctuation :

Code : Tout sélectionner

If InStrB(PONCTUATION,caractere) > 0
Le hic, c'est que certains caractère sont remplacés par des "?" lorsque je copie/colle dans l'EDI de RealBasic. Notamment, une des deux formes d'apostrophe( ’ ), mais aussi les différents tirets ( — et – ) et certaines formes de guillemets( “” ).

Du coup, je me demandais si vous aviez un bout de code élégant pour détecter s'il s'agit d'un signe de ponctuation ? Ou faut-il que je compare grâce aux valeurs ascii (ça demande beaucoup plus de code pour la même chose) ?

Re: Caractère non pris en charge par l'EDI

Publié : jeu. 06/déc./2012 18:17
par falsam
Les expressions régulières devraient t'aider à répondre à ta question.

CreateRegularExpression() pour créer l'expression régulière.
MatchRegularExpression() pour vérifier que la chaîne traitée contient bien l'expression régulière créée précédemment.

Exemple de création d'expression réguliére pour tester qu'une chaine contient bien des chiffres de 0 à 9.
Les crochets [] définissent la liste de caractères autorisés.

Code : Tout sélectionner

*RegMatch = CreateRegularExpression(#PB_Any ,"[0-9]") 
Le code ci-dessous retournera #True

Code : Tout sélectionner

debug MatchRegularExpression (*RegMatch, "123")
le code ci-dessous retournera #False

Code : Tout sélectionner

Debug MatchRegularExpression (*RegMatch, "Pure Basic")
Encore un exemple pour tester des balises h1 à h6 dans une chaîne html

Code : Tout sélectionner

*RegMatch = CreateRegularExpression(#PB_Any ,"<h[1-6]>")
Debug MatchRegularExpression (*RegMatch, "<h1>Une balise de titre HTML</h1>")
Revenons à ta demande. Il existe une classe pour tester les ponctuations.

Code : Tout sélectionner

*RegMatch = CreateRegularExpression(#PB_Any ,"[[:punct:]]")
Buffer$="Une phrase ponctuée par des , des ."
Debug MatchRegularExpression (*RegMatch, Buffer$)

Re: Caractère non pris en charge par l'EDI

Publié : jeu. 06/déc./2012 19:48
par graph100
si tu veux aller un peu plus loin avec les regex :

Code : Tout sélectionner

;{ LIB code

; AIDE à :
; http://www.lumadis.be/regex/test_regex.php

ImportC ""
	pb_pcre_exec(*pcre,*extra,subject.s,length,startoffset,options,*ovector,ovecsize)
EndImport


Structure List_Extraction
	Array Extract.s(0)
EndStructure


Procedure.s BackrefReplaceRegularExpression(regexp_handle, string.s, replacement.s, maximum_reference.l = 10) ; 0 <= maximum_reference <= 99
	Static Dim pcre_results(202)
	
	Protected depart.l, char$, rpl.s, tableau_ref.l, tag$, p1.l, q1.l
	
	depart = 0
	
	While pb_pcre_exec(PeekL(regexp_handle), 0, string, Len(string), depart, 0, @pcre_results(), 202) > 0
		; pcre_exec(PeekL(regexp_handle), 0, string, Len(string), pcre_results(1), 0, @pcre_results(), 202)
		
		rpl.s = replacement
		
		p = pcre_results(0)
		q = pcre_results(1)
		If FindString(replacement,"$0", 1)
			rpl = ReplaceString(rpl, "$0", PeekS(@string + p, q - p))
			
		EndIf
		
		tableau_ref = 2
		
		For _a = 1 To maximum_reference
			tag$ = "$" + Str(_a)
			
			If FindString(replacement, tag$, 1)
				p1 = pcre_results(tableau_ref)
				q1 = pcre_results(tableau_ref + 1)
				rpl = ReplaceString(rpl, tag$, PeekS(@string + p1, q1 - p1))
				
			EndIf
			
			tag$ = "$#" + Str(_a)
			
			position.l = FindString(replacement, tag$, 1)
			If position
				char$ = Mid(replacement, position+Len(tag$), 1)
				
				p1 = pcre_results(tableau_ref)
				q1 = pcre_results(tableau_ref + 1)
				rpl = ReplaceString(rpl, tag$, RSet("",Len(PeekS(@string + p1, q1 - p1)),char$))
				
			EndIf
			
			tableau_ref + 2
		Next
		
		depart = p + Len(rpl)
		
		string = Left(string, p) + rpl + Right(string, Len(string) - q)
	Wend
	
	ProcedureReturn string
EndProcedure

Procedure.s BackrefExtractRegularExpression(regexp_handle, string.s, Array Extract.b(1), List Resultat.List_Extraction()) ; 0 <= Taille tableau Extract <= 99
	Static Dim pcre_results(202)
	
	depart = 0
	
	maximum_reference = ArraySize(Extract())
	
	ClearList(Resultat())
	
	While pb_pcre_exec(PeekL(regexp_handle), 0, string, Len(string), depart, 0, @pcre_results(), 202) > 0
		; pcre_exec(PeekL(regexp_handle), 0, string, Len(string), pcre_results(1), 0, @pcre_results(), 202)
		
		AddElement(Resultat())
		Dim Resultat()\Extract(maximum_reference)
		
		p = pcre_results(0)
		q = pcre_results(1)
		If Extract(0) = #True
			Resultat()\Extract(0) = PeekS(@string + p, q - p)
		EndIf
		
		tableau_ref = 2
		
		For _a = 1 To maximum_reference
			
			If Extract(_a) = #True
				p1 = pcre_results(tableau_ref)
				q1 = pcre_results(tableau_ref + 1)
				
				Resultat()\Extract(_a) = PeekS(@string + p1, q1 - p1)
			EndIf
			
			tableau_ref + 2
		Next
		
		depart = p ; + Len(rpl)
		
		string = Left(string, p) + Right(string, Len(string) - q)
	Wend
	
	ProcedureReturn string
EndProcedure


;}

; in punct : [\]\[!"#$%&'()*+,./:;<=>?@\^_`{|}~-]

; REGEX$ = "([[:punct:]])(.*?)([[:punct:]])"
REGEX$ = "([\("+Chr(34)+"“«<\[{-])(.*?)([\)"+Chr(34)+"”»>\]}-])"
rh = CreateRegularExpression(#PB_Any ,REGEX$)

CHAINE$ = "How To find "+Chr(34)+"the"+Chr(34)+" And "+Chr(34)+"these"+Chr(34)+" followed by a word (To capture) in the «following» text."


Debug "#### Recurrent Replacement test :"
Debug ""
Debug "Starting text :"
Debug CHAINE$
Debug "Regex = ||" + REGEX$ + "||"
Debug ""
Debug "Result :"
Debug BackrefReplaceRegularExpression(rh, CHAINE$, "_$0_")


; creation of the array specifying which parenthesis must be returned
Dim tableau_extraction.b(3)

; we want all parenthesis so we complete the array all the way
For a = 0 To 3
	tableau_extraction(a) = #True
Next


; creation of the list returning the result
NewList Result.List_Extraction()


; processing
BackrefExtractRegularExpression(rh, CHAINE$, tableau_extraction(), Result())

Debug ""
Debug ""
Debug "#### Recurrent extraction test :"
Debug ""
Debug "Starting text :"
Debug CHAINE$
Debug "Regex = ||" + REGEX$ + "||"
Debug ""
Debug "Extracted values :"
Debug ""

b = 0
ForEach Result()
	Debug "Occurrence " + Str(b)
	
	For a = 0 To 3
		Debug "$" + Str(a) + " = " + Result()\Extract(a)
	Next
	
	b + 1
Next

Debug ""
Debug "exemple dans lequel on remplace les mots entre ponctuation par autant de '_' qu'il y avait de lettres."
Debug ""
Debug BackrefReplaceRegularExpression(rh, CHAINE$, "$1$#2_$3", 3)
Il est possible de modifier BackrefReplaceRegularExpression() pour que le nombre de _ corresponde au nombre de lettre d'avant.
Tu peux utiliser le lien suivant pour tester des regex facilement : test_regex

J'en profite pour mentionner que les options de creation de regex sont un peu "pauvre", par exemple, on ne peux pas utilsier l'option U (ungreedy). Il faut la mentionner à chaque fois dans la regex.. C'est dommage.

Re: Caractère non pris en charge par l'EDI

Publié : sam. 08/déc./2012 8:50
par gibet_b
Merci 1000 fois à vous pour vos suggestions et vos nombreux exemples. Grâce à eux, je vais peut-être enfin trouver le courage de me mettre aux regex 8)

Je vous tiens au courant de mes aventures :)

Re: Caractère non pris en charge par l'EDI

Publié : dim. 09/déc./2012 0:28
par graph100
J'ai modifié le code de mon post ci-dessus pour qu'il corresponde plus à ce que tu voulais faire.

La regex suivante : ([\("“«<\[{-])(.*?)([\)"”»>\]}-])
permet de capturer le caractère de ponctuation ouvrant, puis le texte à l'intérieur, et enfin le caractère fermant.
$0 correspond au texte qui match l'expression reg.
$1 est le premier caractère ouvrant, $2 le texte au milieu, $3 le caractère fermant.

Le problème de cette expression est que si les caractères ne sont pas correctement définis, il vont quand même fonctionner :
dans la phrase "suivante), la regex va capturer "suivante)... même si les caractères ne correspondent pas.
Enfin, c'est pas trop grave.

Tu peux aussi définir une regex pour ne capture le texte que si il n'y a qu'un seul mot entre les caractères de capture :

Code : Tout sélectionner

REGEX$ = "([\("+Chr(34)+"“«<\[{-])(\w*?)([\)"+Chr(34)+"”»>\]}-])"

Caractère non pris en charge par l'EDI

Publié : dim. 09/déc./2012 11:45
par wood51
Gibet_b: pour les regex tu peut essayer le log gratuit RegexCoach c'est super pour tester c'est regex avant de les inclurent dans les codes . Moi qui suis une burne en regex je suis fan !!!

@+ wood51

Re: Caractère non pris en charge par l'EDI

Publié : dim. 09/déc./2012 11:54
par Ar-S
Salut Gibet_b,
Je t'invite à parcourir et étudier ce topic. On y a mis pas mal d'exemples.

Re: Caractère non pris en charge par l'EDI

Publié : mar. 11/déc./2012 18:23
par gibet_b
Me revoilà pour chercher un peu d'éclaircissement sur les très obscurs expressions régulières 8)

Pour résoudre mon problème, je voulais tester si le code ascii "renvoyé" par :

Code : Tout sélectionner

MatchRegularExpression (*RegPonctuation, Str(Asc(caractere)))
était bien compris dans certaines plages, avec "l'expression régulière suivante" :

Code : Tout sélectionner

Define *RegPonctuation = CreateRegularExpression(#PB_Any ,"[33-47]|[91-93]|[123-125]|130|[132-133]|[145-151]|171|180|187")
Mais visiblement, ce n'est pas ainsi qu'on formule une telle expression régulière.

Pourriez-vous m'aider à reformuler ?

Re: Caractère non pris en charge par l'EDI

Publié : mer. 12/déc./2012 0:46
par graph100
gibet_b a écrit :Pour résoudre mon problème, je voulais tester si le code ascii "renvoyé" par :

Code : Tout sélectionner

MatchRegularExpression (*RegPonctuation, Str(Asc(caractere)))
était bien compris dans certaines plages, avec "l'expression régulière suivante" :
MatchRegularExpression () ne renvoie pas code ascii ?? mais je pense que j'ai mal compris ou bien la question est mal posée :!: :?:

Sinon, je ne crois pas que tu puisse définir des classes de caractères à partir de leur code ascii tel que tu l'as fait.
Fait une recherche sur le web.

la regex suivante : "123|145" va correspondre à la chaine de caractère '123' et aussi '145', et non au caractère chr(123)...

Mmh, avec "Str(Asc(caractere))" tu cherches a faire quoi ? n'oublie pas que dans certain cas utiliser Findstring() est plus efficace !

Re: Caractère non pris en charge par l'EDI

Publié : mer. 12/déc./2012 2:53
par Ar-S
Je veux bien un exemple concret de ce que tu veux faire pour cerner ta demande.
Là j'ai compris que tu cherches à tester si une chaine.s comporte des caractères de chr(xx) à chr(xx) c'est ça ?

Re: Caractère non pris en charge par l'EDI

Publié : mer. 12/déc./2012 9:43
par gibet_b
Merci à tous les deux.

J'ai bien pensé que je n'avais peut-être rien compris aux expressions régulières :?

Alors, je vais essayer d'expliquer mon raisonnement.

Etant donné que lorsque je copie/colle certains caractères dans l'EDI, ils sont remplacés par des « ? », je ne peux pas faire un simple :

Code : Tout sélectionner

IF caractère = "—"
(ou une quelconque recherche de ce caractère dans une chaine composée de tous les signes de ponctuation qui m'intéresse)

Mon idée est donc de voir si le code ASCII du caractère saisi par l'utilisateur se situe dans telle ou telle plage, ou s'il est égal à telle valeur.

Grâce à :

Code : Tout sélectionner

Define *RegPonctuation = CreateRegularExpression(#PB_Any ,"[33-47]|[91-93]|[123-125]|130|[132-133]|[145-151]|171|180|187")
J'espérais vérifier que le code ASCII du caractère se situait entre 33 et 47, ou entre 91 et 93, ou entre 123 et 125, ou est égal à 130, ou est entre 132 et 133, ou est entre 145 et 151, ou est égal à 171, ou est égal à 180, ou est égal à 187.

Code : Tout sélectionner

Asc(caractere)
Renvoie le code ASCII d'un caractère, et j'ai ajouté :

Code : Tout sélectionner

Str(Asc(caractere))
Parce que MatchRegularExpression demande un string comme paramètre.

J'espère avoir été plus clair :oops:

Re: Caractère non pris en charge par l'EDI

Publié : mer. 12/déc./2012 12:03
par falsam
Pour taper des caractères non pris en charge par l'éditeur de Pure basic, utilises la touche Alt + 0 + Asc.
exemple : Alt + 0 + 187 donneras »
gibet_b a écrit :Me revoilà pour chercher un peu d'éclaircissement sur les très obscurs expressions régulières 8)

Pour résoudre mon problème, je voulais tester si le code ascii "renvoyé" par :

Code : Tout sélectionner

MatchRegularExpression (*RegPonctuation, Str(Asc(caractere)))
était bien compris dans certaines plages, avec "l'expression régulière suivante" :

Code : Tout sélectionner

Define *RegPonctuation = CreateRegularExpression(#PB_Any ,"[33-47]|[91-93]|[123-125]|130|[132-133]|[145-151]|171|180|187")
Mais visiblement, ce n'est pas ainsi qu'on formule une telle expression régulière.
Effectivementça ne fonctionne pas. Ma solution n'est pas élégante mais en attendant mieux, elle répond à ta problématique.

Code : Tout sélectionner

Global Ponctuation.s

Ponctuation = "33|34|35|36|37|38|39|40|41|42|43|44|45|46|47"
Ponctuation + "|91|92|93|123|124|125|130|132|133"
Ponctuation + "|145|146|147|148|149|150|151|171|180|187"

Global *RegPonctuation = CreateRegularExpression(#PB_Any ,Ponctuation)

Procedure.l IsPonctuation(caractere.s)
  ProcedureReturn MatchRegularExpression (*RegPonctuation, Str(Asc(caractere)))
EndProcedure

;Quelques ponctuations
Debug IsPonctuation("!")
Debug IsPonctuation(",")
Debug IsPonctuation("»")
Debug Isponctuation("'")

;N'est pas une ponctuation
Debug IsPonctuation("a")
PS : Tu testes bien plus que des ponctuations:p

Re: Caractère non pris en charge par l'EDI

Publié : mer. 12/déc./2012 12:42
par falsam
Ayant oublié deux "|" j'ai corrigé le code précédent.

Re: Caractère non pris en charge par l'EDI

Publié : mer. 12/déc./2012 12:53
par gibet_b
falsam a écrit :Pour taper des caractères non pris en charge par l'éditeur de Pure basic, utilises la touche Alt + 0 + Asc.
exemple : Alt + 0 + 187 donneras »
Eh bien, grâce à cette astuce que je ne connaissais pas, la méthode que j'expose dans le premier post devrait pouvoir fonctionner.

Je vous tiens au courant !

Merci 1000 fois.

Re: Caractère non pris en charge par l'EDI

Publié : mer. 12/déc./2012 12:56
par falsam
Si cette astuces fonctionne chez toi, alors le code suivant fonctionne aussi :)

Code : Tout sélectionner

Global *RegPonctuation = CreateRegularExpression(#PB_Any , "[!-/]|[[]]|[{-}]|[‚]|[„-…]|[‘-—]|[«]|[´]|[»]")

Procedure.l IsPonctuation(caractere.s)
  ProcedureReturn MatchRegularExpression (*RegPonctuation, caractere)
EndProcedure

;Quelques ponctuations
Debug IsPonctuation("!")
Debug IsPonctuation(",")
Debug IsPonctuation("»")
Debug IsPonctuation("«")
Debug Isponctuation("'")

;N'est pas une ponctuation
Debug IsPonctuation("a")