|
Publicité ' | |||||||||||||||||||||||
|
|
#1 | ||||||
|
Membre éclairé
![]() statisticien Inscription : mai 2011 Messages : 212 ![]() |
Bonjour,
je travaille dans le géo-référencement et afin d'améliorer la qualité je veux exploiter les informations contenues dans les compléments d'adresses afin de les nettoyer et d'extraires des informations qui pourront être utiles. Par exemble pour un individu ayant mis en complément d'adresse " BATIMENT FOCH 3EME ETG PORTE 1200" je ne souhaiterais garder que "BATIMENT FOCH". Tout ça c'est théorique biensur , la réalité est plus compliquée... Donc pour réaliser ce nettoyage et cette normalisation j'utilise les expressions régulières de SAS : PRXPARSE et CALL PRXCHANGE Mais cela ne semble pas marcher comme je le souhaite... Voici un bout de mon code avec un exemple Code :
et voici ce que j'obtiens Code :
string2 est la variable nettoyée (c'est à dire tout ce qui peut ressemble à "BATIMENT + numero de batiment doit être enlevé de la chaine) num est la variable censée récuperer le numero de batiment et capture donne une idée ce qui est contenu dans les buffer de capture (du moins je pense, séparée par des w minuscules Pour les observations 1 4 et 5 tout se passe normalement. Pour l'observation 6 le batiment + numero de batiment n'est pas reconnu ce qui était prévu à l'écriture, j'ai délibérement souhaité reconnaitre des batiments "simples" dans un premier temps style batiment "B1" ou "2C" et par 45F ou "FOCH" etc... Par contre pour les observations 2 et 3 si le nettoyage (string2) se passe tout a fait comme attendu, la récupération du numero de batiment ne se passe pas bien du tout puisque je récupère "2 ETG 4" à la place de "2" et "2A ESC C APPT 27" à la place de "2A" ... Et là je ne comprend plus du tout ce que je pensais avoir compris du fonctionnement des expressions régulières dans SAS , sachant que je m'y suis mis depuis peu. Est-ce un bug ou est-ce moi qui m'y prend mal dans la rédaction de mon code ? Pourriez-vous m'indiquer ce qui ne marche pas et comment y remédier ? Voici la log au besoin Code :
|
||||||
|
|
00
|
|
|
#3 | ||||||||
|
Membre éclairé
![]() statisticien Inscription : mai 2011 Messages : 212 ![]() |
Bonjour
Citation:
alors là oui, je ne savais pas que ça marchait aussi comme ça, mais il me semble que ça ne me donne pas vraiment d'éléments pour la résolution de mon problème... :/ Citation:
J'y ai bien jeté un oeil, je regarde ça depuis la semaine passée en fait, toujours un peu difficile l'anglais pour moi ^^ , mais je n'ai rien trouvé qui puisse m'expliquer vraiment ce qu'il se passe dans mon problème actuel. C'est à partir de cette note que j'ai écris en grande partie mon code SAS avec des expressions régulières. OUI... Je sais... mais en l'occurence je travaille sous SAS uniquement EDIT : J'ai résolu partiellement mon problème, enfin il est résolu, mais je met partiellement, car il y a quelque chose que je ne comprend pas dans l'appel de la fonction prxchange. J'ai contourné mon problème en combinant prxmatch et prxposn qui me donnent finalement le résultat attendu. voici mon code modifié Code :
Code :
Code :
et pour finir par une boutade parce que je n'aimerais pas mourrir idiot... Merci à tous. Concernant les formes régulières sous SAS , il y a cette petite synthèse basique fort utile à avoir sous la main. http://support.sas.com/rnd/base/data...-tip-sheet.pdf |
||||||||
|
|
00
|
|
|
#4 | ||
|
Membre du Club
![]() Fabien Inscription : novembre 2008 Messages : 59 ![]() |
Salut,
J'ai peut etre pas tout compris ce que tu cherches à faire mais le code ci dessous recupere le 'truc' apres BATIMENT. Code :
|
||
|
|
00
|
|
|
#5 | ||
|
Membre éclairé
![]() statisticien Inscription : mai 2011 Messages : 212 ![]() |
oui je cherche a récupérer le truc après BATIMENT MAIS afin de ne pas récupérer tout et n'importe quoi je veux que ça ai un "sens" dans un premier temps, car c'est essentiel pour faire un bon nettoyage.
Et donc je cherche a faire ça à la seule condition que cela "ressemble" à quelque chose qui peut vraisemblablement être un numéro de bâtiment comme : "5" "A" "B2" "2C" "1200" mais je ne désire pas récupérer "DROITE" dans "BATIMENT DROITE" ou "FOND" dans "BATIMENT FOND DE COUR" ou "SOL" de "BATIMENT SOL" et non plus "LE" de "BATIMENT LE FLOREAL" auquel je n'ai pas encore pensé ceci dit en passant...(enfin presque...) C'est pourquoi j'ai défini le motif "[0-9A-Z][0-9A-Z]?[0-9]{0,2}?\s)" correspondant à ce à quoi doit ressembler le numéro du bâtiment( c'est à dire si j'ai bien tout compris) $3. Si ça correspond pas, je laisse et je m'en occupe plus tard. Je nettoie par étape, car on rencontre vraiment tout et n'importe quoi dans le complément d'adresse, donc voilà pour répondre a ton interrogation, ton code marche sans doute mais je veux qu'il respecte une certaine contrainte sinon on ne doit rien faire et on passe aux étapes suivantes du nettoyage par exemple récupérer le numéro de porte ou de logement, puis l'escalier etc... Par contre ton exemple viens de me faire réaliser comment fonctionnait un peu prxchange, par contre cela ne m'explique pas pourquoi ces deux expressions régulières conduisent au même résultat Code :
|
||
|
|
00
|
|
|
#6 | |
![]() ![]() Samir SELMANEConsultant en Business Intelligence Inscription : février 2011 Messages : 1 006 ![]() |
Citation:
![]() Tu n'as pas une table ou un fichier où tu pourras récupérer les valeurs possibles du numéro de bâtiment? L’idée que j’imagine est : 1-de faire une condition si le résultat renvoyé par les expressions regu appartient à cette liste donc à garder sinon à nettoyer. (Bien sûre si tu ne les a pas quelque part dans une table ou dans fichiers tu ne va pas les saisir à la main). Si tu les as alors tu pourras les récupérer dans une macro variable avec une call symput et faire boucle avec condition comme dans 1. Le problème qui se pose dans ton cas c’est comment faire la distinction entre ce qu’il faut garder et ce qu’il supprimer /zapper. Il y a-t-il un critère particulier ? Sa sera difficile de proposer une solution puisqu’on ne connaît pas les valeurs possibles du numéro de bâtiment. Avec un peu plus de détails on/t’y arrivera. |
|
|
|
00
|
|
|
#7 | ||||
|
Membre éclairé
![]() statisticien Inscription : mai 2011 Messages : 212 ![]() |
Pour ton 1- , la liste quelque part c'est un peu ce que je cherche à faire
et je ne peux pas en faire une à la main vu que je suis sur des tables france entière avec 50 millions d'individus Donc je suis obligé d'y aller à l'aveugle, de repérer les cas "classiques" de les traiter, et ensuite revenir sur les moins "classiques", les traiter, et regarder ce que je peux récupérer encore, après je fais de la stat donc a un certain niveau de récupération lorsque les cas seront trop tordus et rares je laisserais tomber Mon critère actuel ici c'est (Lettre ou chiffre) + (peut etre encore une lettre ou chiffre) + (éventuellement encore deux chiffres) suivi d'un blanc soit [0-9A-Z][0-9A-Z]?[0-9]{0,2}?\s Pour le code j'ai trouvé, j'ai fait légèrement autrement Code :
je continue ce fil parce ce que je ne comprend pas pourquoi ce code ci-dessus marche, alors que celui ci-dessous ne marche pas !! Code :
A ce stade, sans autres explications je le prend pour un BUG de SAS.... ??? voili voilou Si quelqu'un a une idée.... |
||||
|
|
00
|
|
|
#8 | ||
|
Membre éclairé
![]() statisticien Inscription : mai 2011 Messages : 212 ![]() |
Problème résolu, c'était un problème de définition de l'expression régulière j'avais mis des ? en redondance (ceux en rouge).... :/
ch_BATIMENT2= prxparse("s/(.{0,46}?)(\sBATIMENT\s?)([0-9A-Z][0-9A-Z]?[0-9]{0,2}?\s)(.{0,46}?)/$3/"); En les supprimant cela marche sans problème comme attendu..... !!! Code :
|
||
|
|
00
|
|
|
#9 | ||
|
Membre confirmé
![]() Inscription : janvier 2010 Messages : 185 ![]() |
Bonjour jerome_pdv2,
Je me permets de porter une critique que j'espère constructive à ton utilisation des expressions régulières : Code :
s/(.{0,46})(\sBATIMENT\s?)([0-9A-Z][0-9A-Z]?[0-9]{0,2}\s)(.{0,46})/$3/ Ici tu substitues le tout (l'adresse complète) par la partie (le numéro du batiment). Cela revient en fait à récupérer le numéro du batiment et t'oblige à décrire de façon fastidieuse l'intégralité de ta chaine en utilisant l'astuce de commencer et de finir ta regexp par .{0,46}. Donc en utilisant une regexp de type // au lieu de s/// les 2 sous-chaines .{0,46} deviennent superflues et ton expression devient : Code :
/(\sBATIMENT\s?)([0-9A-Z][0-9A-Z]?[0-9]{0,2}\s)/ Ce qui t'intéresse c'est le numéro du batiment, çad [0-9A-Z][0-9A-Z]?[0-9]{0,2}\s. Donc contentons nous de placer des parenthèses autour de ce seul numéro. Cela libérera de la mémoire et du temps de traitement. On obtient: Code :
/BATIMENT\s?([0-9A-Z][0-9A-Z]?[0-9]{0,2}\s)/ Maintenant que tu as un unique buffer $1, il te faut le récuperer grace à la fonction prxposn : Code :
te suffit je vais en rester là. On a déjà gagné en lisibilité et en efficacité. |
||
|
|
10
|
|
|
#10 | ||||||||
|
Membre éclairé
![]() statisticien Inscription : mai 2011 Messages : 212 ![]() |
Bonjour et merci de ta critique constructive... (d'ailleurs j'écris rarement de façon optimale lol)
mais enfin... je n'ai pas que le seul but du numéro... Je veux récupérer le numéro de batiment effectivement, mais je veux aussi "nettoyer" mon complément d'adresse par exemple j'ai un complément d'adresse comme ceci : COMPLEMENT ="BLABLABLA1 BATIMENT 2 BLABLABLA2" Je veux avoir en sortie : 1 - Le numéro de bâtiment effectivement BATIMENT='2' mais aussi 2 - le complément d'adresse nettoyé en COMPLEMENT_NETTOYE="BLABLABLA1 BLABLABLA2" Que je vais ensuite explorer de nouveau pour trouver des choses signifiantes (numero de logement, d'etage, d'escalier etc...) donc si ma forme régulière à cette forme c'est parce que j'utilise aussi les buffer de capture 1 et 4 pour construire le complément nettoyé... voici le code complet Code :
num pour le numero de bâtiment extrait ET string_nettoye pour la chaine nettoyée de BATIMENT + numero de bâtiment Code :
Donc effectivement pour récupérer le numéro de batiment, je peux faire la modification que tu suggère ce sera effectivement plus simple j'avoue. Mais en fait j'avais juste repris le motif du nettoyage présent dans ch_BATIMENT pour ch_BATIMENT2 Et en fait j'aimerais bien déclarer une seule et même forme régulière pour faire les deux opérations... ce qui serait sans doute plus économique... car dans une dernière modification mes formes régulières sont devenues... Code :
![]() ![]() ![]() Edit : Du coup j'ai fait la chose avec une seule forme régulière et deux scan puis supprimé le buffer pour " BATIMENT" Peut-être est ce que cela utilisera moins de ressources comme ceci... De plus j'ai modifié mes formes {0,46} par la forme plus générale .* il semble que SAS la digère mieux ... Code :
Re-Edit : selon toi je devrais plutôt privilieger l'utilisation de prxmatch, et 3 prxposn et de l'expression // à la place d'un prxchange,de l'expression s/// et de deux scan ? |
||||||||
|
|
00
|
|
|
#11 | ||
|
Membre confirmé
![]() Inscription : janvier 2010 Messages : 185 ![]() |
Bonjour
ça m'apprendra à lire tous les messages Voici ce que je te propose :
Code :
|
||
|
|
00
|
|
|
#12 |
|
Membre éclairé
![]() statisticien Inscription : mai 2011 Messages : 212 ![]() |
ok merci pour le tuyau, effectivement j'ai toujours du mal à voir ce pour quoi est fait prxchange (ce qui est quand même dans le nom de l'instruction ) et je ne l'utilise pas de façon optimale du coup.
Je reviendrais après des test comparatifs de rapidité |
|
|
00
|
|
|
#13 | ||||||||
|
Membre confirmé
![]() Inscription : janvier 2010 Messages : 185 ![]() |
Tu dois bien voir un petit peu à quoi ça sert, non ? Parce que sinon tu ne serais pas arriver à ta solution... ou alors tu as beaucoup de chance.
On va repartir du début : PRXPARSE sert à compiler une expression régulière (regexp) et renvoie un code qui sert à "étiqueter" cette expression compilée et à l'utiliser dans les autres fonction PRX. A chaque iteration du PDV (a chaque ligne traitée), Le code vaut 1 pour la premiere regexp compilée, 2 pour la deuxième, etc. On pourrait se passer de cette étape de pré-compilation et écrire directement les regexp dans les autres fonctions PRX comme ici: Code :
1. l'expression est compilée à chaque exécution de la(des) fonction(s) qui l'utilise(nt). 2. Il faut retaper l'expression chaque fois qu'on veut l'utiliser dans une fonction. Dans notre exemple : Code :
position_de_toto=prxmatch("/toto/", texte); Code :
Ici il n'y a qu'une seule fonction donc finalement on y perd du point de vue du développeur feignant. Mais il y a encore mieux : conditionner la compilation par _N_=1 et retenir la valeur reg. Cela évitera le travail de compilation de la même expression à chaque itération du PDV : SAS va conserver dans sa mémoire l'expression compilée dès la premiere itération sans jamais l'écraser par une recompilation. On pourra utiliser cette regexp autant de fois que nécessaire en utilisant simplement l'étiquette conservée dans reg. D'où l'écriture un peu fastidieuse du retain + if _n_=1 then prxparse dans les exemples donnés par SAS. Ce sont des habitudes de programmation à prendre même sur des exemples simples car ils évitent des écueils sur les programmes plus compliqués. Code :
Elle ne fonctionne qu'avec des regexp de subtitution c'est à dire de la forme s/chaine a substituer/substitu/. Code :
|
||||||||
|
|
00
|
|
|
#14 | ||||
|
Membre éclairé
![]() statisticien Inscription : mai 2011 Messages : 212 ![]() |
oui, lorsque je disais j'ai du mal à voir, c'est qu'en fait je raisonnais toujours par une description totale de la chaine, alors que prxchange travaille aussi sur des portions de la chaine.
Je m'attaque à des choses plus compliquées maintenant les étages... ![]() J'ai repris ton code comme départ Code :
Code :
|
||||
|
|
00
|
|
|
#15 | ||
|
Membre éclairé
![]() statisticien Inscription : mai 2011 Messages : 212 ![]() |
Quelques questions au spécialistes ou non... :
1- Les buffers font perdre du temps, mais les parenthèses "sans capture" c'est à dire les expressions du type (?:...) font elles en perdre autant où bien sont elles plus légères ? 2 - Y a t il moyen de définir des "sous motifs" à l'intérieur de nos motifs ? Ou on passe éventuellement par des macros variables ? par exemple en écriture "approximative" motif_de_base=prxparse(/blabla de base/); motif_elaboré=prxparse(/truc1 (appel de motif_de_base) truc2 (appel de motif_de_base) truc3/); 3 - Quelle est la longueur maximale de la chaine de caractères définissant une regexp ? Je me pose ces questions là car je commence à avoir des choses compliquées à base de briques élémentaires.., et j'aimerais pouvoir en simplifier l'écriture ainsi que la lecture. Code :
|
||
|
|
00
|
Copyright © 2000-2012 - www.developpez.com