Précédent   Forum des professionnels en informatique > Logiciels > Solutions d'entreprise > Business Intelligence > SAS > SAS Base
SAS Base Forum d'entraide sur SAS base : étape data, procédures non statistiques, procédures non graphiques, SQL
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 05/01/2012, 21h59   #1
Membre éclairé
 
Homme
statisticien
Inscription : mai 2011
Messages : 213
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : statisticien
Secteur : Administration - Collectivité locale

Informations forums :
Inscription : mai 2011
Messages : 213
Points : 319
Points : 319
Par défaut REGEX : Problème avec les assertions arrières

Bonjour,

je réalise des REGEX pour normaliser des chaines de caractères complexes présentes dans mes données.

J'ai écrit un bout de code avec des assertions arrières qui pose pas de problèmes

voici un exemple

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 
DATA a;
length var $40;
var='totoAB CD';output;
var='totoA CD';output;
var='*V* *D3 *I*TiTiToTo*I*';output;
var='*I* *D3 *I*Pif&Paf*I*';output;
var='*IN* *D3 *I*Pif&Paf*I*';output;
var='*V* *D3 TaTa';output;
var='*N* *D3 *I*TiTiToTo*I*';output;
run;
 
DATA b; SET a;
retain regex;
IF _n_=1 then do;
regex=prxparse('s/(?<=[VIL]\*\s\*(?:D[1-9A]|L[1-4]))\s\*[VIL]\*([^\*]+)\*[VIL]\*\s/# $1 /');
end;
IF prxmatch(regex,var) then var2=prxchange(regex,1,var);
run;
proc print DATA=b;run;
qui me fait quelques transformations (cf ci dessous)

Code :
1
2
3
4
5
6
7
8
9
10
 
                     Obs    var                       regex          var2
 
                      1     totoAB CD                   1
                      2     totoA CD                    1
                      3     *V* *D3 *I*TiTiToTo*I*      1      *V* *D3# TiTiToTo
                      4     *I* *D3 *I*Pif&Paf*I*       1      *I* *D3# Pif&Paf
                      5     *IN* *D3 *I*Pif&Paf*I*      1
                      6     *V* *D3 TaTa                1
                      7     *N* *D3 *I*TiTiToTo*I*      1
Les transformations sont déterminées par les balises *caractère*

Je voulais faire des variantes à deux caractères de mes balises*

Par exemple je voulais que la regex reconnaisse non seulement
*V* , *I* et *L* mais également *VN* , *IN* et *LN*

Donc je me suis dit, c'est simple il suffit de remplacer la description de tes balises qui s'écrivent en [VIL]\* ou \*[VIL]\*
par [VIL]N?\* ou \*[VIL]N?\*

et là à ma grande surprise SAS n'accepte pas à la compilation

Code :
1
2
3
4
5
6
7
8
 
DATA b; SET a;
retain regex;
IF _n_=1 then do;
regex=prxparse('s/(?<=[VIL]N?\*\s\*(?:D[1-9A]|L[1-4]))\s\*[VIL]N?\*([^\*]+)\*[VIL]N?\*\s/# $1 /');
end;
IF prxmatch(regex,var) then var2=prxchange(regex,1,var);
run;
ce qui donne en log

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
 
ERROR: Variable length lookbehind NOT implemented before HERE mark IN regex
       m/(?<=[VIL]N?\*\s\*(?:D[1-9A]|L[1-4]))\s\*[VIL]N?\*([^\*]+)\*[VIL]N?\*\s << HERE /.
 
ERROR: The regular expression passed TO the FUNCTION PRXPARSE contains a syntax error.
NOTE: Argument 1 TO FUNCTION PRXPARSE at line 9601 COLUMN 7 IS invalid.
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9603 COLUMN 4 IS invalid.
var=totoAB CD regex=. var2=  _ERROR_=1 _N_=1
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9603 COLUMN 4 IS invalid.
var=totoA CD regex=. var2=  _ERROR_=1 _N_=2
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9603 COLUMN 4 IS invalid.
var=*V* *D3 *I*TiTiToTo*I* regex=. var2=  _ERROR_=1 _N_=3
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9603 COLUMN 4 IS invalid.
var=*I* *D3 *I*Pif&Paf*I* regex=. var2=  _ERROR_=1 _N_=4
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9603 COLUMN 4 IS invalid.
var=*IN* *D3 *I*Pif&Paf*I* regex=. var2=  _ERROR_=1 _N_=5
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9603 COLUMN 4 IS invalid.
var=*V* *D3 TaTa regex=. var2=  _ERROR_=1 _N_=6
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9603 COLUMN 4 IS invalid.
var=*N* *D3 *I*TiTiToTo*I* regex=. var2=  _ERROR_=1 _N_=7
NOTE: Mathematical operations could NOT be performed at the following places. The results of the
      operations have been SET TO missing VALUES.
      Each place IS given BY: (Number of times) at (Line):(COLUMN).
      1 at 9601:7   7 at 9603:4
NOTE: There were 7 observations READ FROM the DATA SET WORK.A.
NOTE: The DATA SET WORK.B has 7 observations AND 3 VARIABLES.
NOTE: Compressing DATA SET WORK.B increased size BY 100.00 percent.
      Compressed IS 2 pages; un-compressed would require 1 pages.
NOTE: DATA statement used (Total process time):
      real time           0.01 seconds
      cpu time            0.01 seconds
Je me dit ok c'est le ? qui pose problème donc j'ai remplacé le
([VIL]N?) par (?:[VIL]N|[VIL])

Code :
1
2
3
4
5
6
7
8
9
 
DATA b; SET a;
retain regex;
IF _n_=1 then do;
regex=prxparse('s/(?<=(?:[VIL]N|[VIL])\*\s\*(?:D[1-9A]|L[1-4]))\s\*(?:[VIL]N|[VIL])\*([^\*]+)\*(?:[VIL]N|[VIL])\*\s/# $1 /');
end;
IF prxmatch(regex,var) then var2=prxchange(regex,1,var);
run;
proc print DATA=b;run;
etv là paf ! même problème

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
 
ERROR: Variable length lookbehind NOT implemented before HERE mark IN regex
       m/(?<=(?:[VIL]N|[VIL])\*\s\*(?:D[1-9A]|L[1-4]))\s\*(?:[VIL]N|[VIL])\*([^\*]+)\*(?:[VIL]N|[VIL])
       \*\s << HERE /.
 
ERROR: The regular expression passed TO the FUNCTION PRXPARSE contains a syntax error.
NOTE: Argument 1 TO FUNCTION PRXPARSE at line 9609 COLUMN 7 IS invalid.
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9611 COLUMN 4 IS invalid.
var=totoAB CD regex=. var2=  _ERROR_=1 _N_=1
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9611 COLUMN 4 IS invalid.
var=totoA CD regex=. var2=  _ERROR_=1 _N_=2
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9611 COLUMN 4 IS invalid.
var=*V* *D3 *I*TiTiToTo*I* regex=. var2=  _ERROR_=1 _N_=3
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9611 COLUMN 4 IS invalid.
var=*I* *D3 *I*Pif&Paf*I* regex=. var2=  _ERROR_=1 _N_=4
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9611 COLUMN 4 IS invalid.
var=*IN* *D3 *I*Pif&Paf*I* regex=. var2=  _ERROR_=1 _N_=5
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9611 COLUMN 4 IS invalid.
var=*V* *D3 TaTa regex=. var2=  _ERROR_=1 _N_=6
NOTE: Argument 1 TO the FUNCTION PRXMATCH IS missing.
ERROR: Argument 1 TO the FUNCTION PRXMATCH must be a positive integer returned BY PRXPARSE FOR a
       valid pattern.
NOTE: Argument 1 TO FUNCTION PRXMATCH at line 9611 COLUMN 4 IS invalid.
var=*N* *D3 *I*TiTiToTo*I* regex=. var2=  _ERROR_=1 _N_=7
NOTE: Mathematical operations could NOT be performed at the following places. The results of the
      operations have been SET TO missing VALUES.
      Each place IS given BY: (Number of times) at (Line):(COLUMN).
      1 at 9609:7   7 at 9611:4
NOTE: There were 7 observations READ FROM the DATA SET WORK.A.
NOTE: The DATA SET WORK.B has 7 observations AND 3 VARIABLES.
NOTE: Compressing DATA SET WORK.B increased size BY 100.00 percent.
      Compressed IS 2 pages; un-compressed would require 1 pages.
NOTE: DATA statement used (Total process time):
      real time           0.00 seconds
      cpu time            0.00 seconds
or à regarder mon code, j'ai déjà dans l'assertion arrière une expression similaire qui ne pose pas de problèmes à la compilation Je n'y comprend pas grand chose, où se situe le problème ?
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2012, 23h22   #2
Rédacteur
 
Homme Stéphane
Consultant et formateur SAS et Cognos
Inscription : avril 2009
Messages : 1 791
Détails du profil
Informations personnelles :
Nom : Homme Stéphane
Localisation : France, Yvelines (Île de France)

Informations professionnelles :
Activité : Consultant et formateur SAS et Cognos
Secteur : Conseil

Informations forums :
Inscription : avril 2009
Messages : 1 791
Points : 4 012
Points : 4 012
pourquoi tu fais des assertions arrières ?

Pourquoi tu n'attrapes pas déjà ce qui est entre deux * par _reg_etoile= prxparse('/*(.+)*/i'); pour voir déjà ?
__________________
N'oubliez pas de cliquer sur lorsque votre problème est réglé !

Moteur de recherche dans les papiers SAS
datametric est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2012, 01h54   #3
Membre éclairé
 
Homme
statisticien
Inscription : mai 2011
Messages : 213
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : statisticien
Secteur : Administration - Collectivité locale

Informations forums :
Inscription : mai 2011
Messages : 213
Points : 319
Points : 319
Pourquoi je fais des assertions arrières ?

Parce que je fais de la grammaire !

Le résultat obtenu dans la première proc print est bien celui que je veux dans les cas

Code :
1
2
                      3     *V* *D3 *I*TiTiToTo*I*      1      *V* *D3# TiTiToTo
                      4     *I* *D3 *I*Pif&Paf*I*       1      *I* *D3# Pif&Paf
Je voudrais aussi en même temps

Code :
1
2
 
                      5     *IN* *D3#  Pif&Paf      1
mais ne surtout rien toucher aux autres.
Il y a des règles bien spéciales qui se cache derrière cette expression régulière.
Il s'agit d'explorer une variable texte d'adresse en regroupant ses différentes composantes par catégories pertinentes.

Pour comprendre un peu
Par exemple

6 RUE DE LA MONTEE DU FORT RESIDENCE LE RICHELIEU
LA RESIDENCE DU QUAI 6 RUE DE LA LIBERTE
ALLEES DES RESIDENCES FLEURIES

Elle se "dépiotte" classiquement avec des mots clés structurants présent dans les adresses comme "RUE" , "MONTEE" , "RESIDENCES" , "QUAI" , "ALLEES"

6 RUE DE LA MONTEE DU FORT RESIDENCE LE RICHELIEU
LA RESIDENCE DU QUAI 6 RUE DE LA LIBERTE
ALLEES DES RESIDENCES FLEURIES

Seulement à priori on ne sait pas vraiment ou couper...
Donc j'essaye de former des mots grâce aux articulations

Premièrement je met mes balises

6 *V*RUE*V* DE LA *V*MONTEE*V* DU *L*FORT*L* *I*RESIDENCE*I* LE RICHELIEU
LA *I*RESIDENCE*I* DU *V*QUAI*V* 6 *V*RUE*V* DE LA LIBERTE
*V*ALLEES*V* DES *L*RESIDENCES*L* FLEURIES

ensuite je réduis les articulations

6 *V*RUE*V* *D1 *V*MONTEE*V* *D2 *L*FORT*L* *I*RESIDENCE*I* *L1 RICHELIEU
*L2 *I*RESIDENCE*I* *D2 *V*QUAI*V* 6 *V*RUE*V* *D1 LIBERTE
*V*ALLEES*V* *D3 *L*RESIDENCES*L* FLEURIES

Je vous passe les étapes, et à la fin je dois arriver à

6 RUE DE_LA_MONTEE_DU_FORT RESIDENCE LE_RICHELIEU
LA RESIDENCE DU_QUAI 6 RUE DE_LA_LIBERTE
ALLEES DES_RESIDENCES_FLEURIES

Mais pour cela je dois désactiver dans certains cas certains balises préalablement mises
"MONTEE" et "FORT" clairement articulées dans RUE DE LA MONTEE DU FORT et ne consituent ni une indication de lieu (FORT) ni de voie "MONTEE"
De même que QUAI dans RESIDENCE DU QUAI
et RESIDENCES DANS RUE DES RESIDENCES FLEURIES

C'est ce à quoi me sert cette REGEX,
mais pour désactiver une balise, faut il encore que je sache si il y a une balise auparavant, car si ce n'est pas le cas c'est que c'est bien une balise valide, comme RUE et RESIDENCE dans "6 RUE DE LA MONTEE DU FORT RESIDENCE LE RICHELIEU".
D'où l'utilité des expressions arrières, non ?
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 06/01/2012, 18h11   #4
Membre éclairé
 
Homme
statisticien
Inscription : mai 2011
Messages : 213
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : statisticien
Secteur : Administration - Collectivité locale

Informations forums :
Inscription : mai 2011
Messages : 213
Points : 319
Points : 319
Après quelques essais, je pense avoir trouvé la raison du problème, qui n'est cependant pas une explication.

Les assertions arrières ne semblent pas supporter les longueurs variables.
Je n'ai aucune idée si ça viens de l'implémentation SAS des Regex de Perl, ou si c'est dans les spécifications de Perl.

Je suis toujours à la recherche d'une solution pour contourner le problème, car je préfère suffixer mes balises *I* éventuellement en *IN* plutot qu'en *J* ce pour des raisons de souplesse et de clareté des traitements.

Une autre solution serait de doubler la lettre ou de la suffixer par 0 pour exprimer qu'elle n'a pas de suffixe, *V* deviendrait *VV* ou encore *V0* *I* deviendrait *II* ou *I0* .
Et mes alternatives se feraient sous longueur fixe, par exemple avec la suffixation en 0
[VIL][0N] à la place de [VIL] devrait pas poser de problème, je trouve ça néanmoins un peu lourd...
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2012, 09h48   #5
Membre éclairé
 
Homme
statisticien
Inscription : mai 2011
Messages : 213
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Paris (Île de France)

Informations professionnelles :
Activité : statisticien
Secteur : Administration - Collectivité locale

Informations forums :
Inscription : mai 2011
Messages : 213
Points : 319
Points : 319
J'en ignore la raison, mais l'explication est ici

Look-Ahead and Look-Behind Behavior

"specifies a zero-width, positive, look-behind assertion. For example, in the expression (?<=regex1) regex2, a match is found if both regex1 and regex2 match. regex1 is not included in the final match. Works with fixed-width look-behind only."


http://support.sas.com/documentation...a003288497.htm

Je n'avais donc pas à aller loin...

et donc pas de longueur variables dans les assertions arrières, par contre elles sont acceptées dans les assertions avant...

Résolu
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 10
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 21h16.


 
 
 
 
Partenaires

Hébergement Web