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 20/12/2011, 12h21   #1
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
Par défaut Vérifier si le dénominateur est nul ou non?

Bonjour les amis,

J'ai besoin d'extraire le dénominateur pour vérifier s'il est nul ou non, par exemple dans cet exemple "(5+3)/4*(3/(4-(2*2))" je veux récupérer les dénominateurs : 4 et (4-(2*2)). J'ai fé ca mais ca marche pas. Merci bien d'avance pour vos réponses.

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
DATA b;
SET a;
length modif $100. motif3 $100.;
retain parenthese_elementaire ;
DROP modif parenthese_elementaire t;
IF _n_=1 then do;
parenthese_elementaire=prxparse('s/(.*)\/(.*)/$1[$3]$5/');
end;
 
t=prxmatch(parenthese_elementaire,calcul);
motif3=translate('('!!strip(prxposn(parenthese_elementaire,3,calcul))!!')','/','|');
modif=prxchange(parenthese_elementaire,1,calcul);
output;
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 13h06   #2
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
Bonjour

tu peux essayer avec ça

(.*)(\/)([^\/]*)(.*) : bidule1 quelconque suivi de '/' suivi d'un bidule ne contenant pas de / , si il y a un deuxième / il sera contenu dans le buffer 4 (prxposn(regexp,4,string))

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
 
DATA a;
ratio='(5+3)/4     ';output;
ratio='(3/(4-(2*2))';output;
ratio='pif/paf';output;
ratio='toto/tata';output;
run;
 
DATA b;
SET a;
retain noyau_denom;
IF _n_=1 then do;
noyau_denom=prxparse('/(.*)(\/)([^\/]*)(.*)/');end;
t=prxmatch(noyau_denom,ratio);
denom=prxposn(noyau_denom,3,ratio);
run;
Par contre 's/(.*)\/(.*)/$1[$3]$5/'
devrait marcher , et tu dois trouver ton dénominateur dans le buffer 2
(prxposn(regexp,2,string))
et si tu la transforme en
's/(.*)(\/)(.*)/$1[$3]$5/' tu dois retrouver ton dénominateur dans le buffer 3 (comme écrit dans ton code)


Edit : enfin si il y a des choses que tu ne comprend ou qui mérite des précisions pose tes questions.
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 15h05   #3
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
Merci Jerom pour votre réponse, j'ai utilisé le code suivant :

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
DATA a;
ratio='45/(2-5/(2*6-(9/8)))';output;
run;
DATA b;
SET a;
retain noyau_denom;
IF _n_=1 then do;
noyau_denom=prxparse('s/(.*)(\/)(.*)/$1|$3|$5/');end;
t=prxmatch(noyau_denom,ratio);
denom=translate(' '!!strip(prxposn(noyau_denom,3,ratio))!!' ','/','|');
modif=prxchange(noyau_denom,1,ratio);
output;
Do i= 1 TO 10;
test=INDEX(ratio,'/');
IF test then do;
ratio=modif;
noyau_denom=prxparse('s/(.*)(\/)(.*)/$1|$3|$5/');
t=prxmatch(noyau_denom,ratio);
denom=translate(' '!!strip(prxposn(noyau_denom,3,ratio))!!' ','/','|');
modif=prxchange(noyau_denom,1,ratio);
output;
end;
else i=100001;
end;
run;
J'obtiens comme résultat :
Denom
--------
8)))
(2*6-(9/8)))
(2-5/(2*6-(9/8)))

Or je veux récupérer le résultat comme suit: 8,(2*6-(9/8)) et (2-5/(2*6-(9/8))), je ne sé po comment gérer le problème de parenthèses de fin.Merci Bien pour votre aide.
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 18h06   #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
Normal, c'est pas gérable en une seule expression régulière !

Enfin peut-être que si mais je ne sais pas faire là.

C'est un problème typique de récursivité, mais je crois que les expressions prx de SAS ne le supporte pas (en tout cas je n'ai jamais vu aucun exemple...).


Pour résoudre ton problème il faut combiner les recherches de parenthèses et la présence de divisions.

Je vais supposer que l'écriture de tes expressions est de la forme A/(B) dès lors que B contient un des opérateurs suivants '+' '-' '*' '/' (j'espère que tu n'en as pas d'autres, mais bon ça pourra se modifier.

Etape 1
Il faut d'abord transformer les 5/8 en 5/(8)

on utilise l'expression régulière ratio_atome pour ce faire

Etape 2
ensuite on repère des dénominateur parenthèses par l'expression régulière parenthese_ratio et on remplace les / par : et les () par []
le résultat sort dans la variable denom

ensuite on repère les parenthèses non dénominateur par l'expression régulière parenthese_elementaire
on remplace les () par []
le résultat sort dans la variable motif

à chaque fois on "redresse" denom et motif en remplaçant :[] par /()
et on remet dans la bonne écriture les 5/(8) à l'aide de l'expression régulière sup_ratio_atome

ensuite on reboucle au début de l'étape 2 tant qu'il y a des choses à faire



J'ai du utiliser 4 expressions régulières, il y a sans doute possibilité de les optimiser et éventuellement d'en réduire le nombre.
Tout ça n'est sans doute pas optimal mais doit te permettre d'avancer.

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
54
55
56
57
58
59
 
 
DATA a;
length calcul $100;
calcul='45/(2-5/(2*6-(9/8)+3/8))';output;
run;
 
 
DATA c;
SET a;
length motif $100 denom $100 calcul_old $100;
retain parenthese_elementaire ratio_et_parenthese ratio_atome sup_ratio_atome;
DROP  parenthese_elementaire ratio_et_parenthese ratio_atome t sup_ratio_atome;
IF _n_=1 then do;
ratio_atome=prxparse("s/(.*\/)([^\(\)\/\-\+\*]+)(.*)/$1($2)$3/");
parenthese_elementaire=prxparse('s/(.*[^\/])(\()([^\(\)]*)(\))(.*)/$1[$3]$5/');
ratio_et_parenthese=prxparse('s/(.*)(\/\()([^\(\)\/]*)(\))(.*)/$1:[$3]$5/');
sup_ratio_atome=prxparse("s/(.*\/)(\()([^\(\)\/\-\+\*]+)(\))(.*)/$1$3$5/");
end;
calcul_old=calcul;
/***** remplace les forme du type 8/5 par 8/(5) / 2/A par 2/(A) etc...  ***/
t=prxmatch(ratio_atome,calcul);
do until (t=0);
call prxchange (ratio_atome,-1,calcul);
t=prxmatch(ratio_atome,calcul);
end;
/***** fin transformation  ***/
/*** boucle reconnaissance parenthèses et ratio ***/
do while (prxmatch(ratio_et_parenthese,calcul)=1 OR prxmatch(parenthese_elementaire,calcul)=1);
/*** boucle reconnaissance ratio ****/
do while (prxmatch(ratio_et_parenthese,calcul)=1);
denom=prxposn(ratio_et_parenthese,3,calcul);
motif='';
calcul=prxchange(ratio_et_parenthese,1,calcul);
denom=translate(denom,'()/','[]:');
       /**** suppression des "ratios atomes" 5/(8) --> 5/8 ***/
do while (prxmatch(sup_ratio_atome,denom));denom=prxchange(sup_ratio_atome,1,denom);end;
       /**** fin suppression des "ratios atomes" 5/(8) --> 5/8 ***/
output;
end;
/*** fin boucle reconnaissance ratio ***/
/*** boucle reconnaissance parenthèses ***/
do while (prxmatch(parenthese_elementaire,calcul)=1);
motif=prxposn(parenthese_elementaire,3,calcul);
denom='';
calcul=prxchange(parenthese_elementaire,1,calcul);
motif=translate(motif,'()/','[]:');
       /**** suppression des "ratios atomes" 5/(8) --> 5/8 ***/
do while (prxmatch(sup_ratio_atome,motif));motif=prxchange(sup_ratio_atome,1,motif);end;
       /**** fin suppression des "ratios atomes" 5/(8) --> 5/8 ***/
output;
end;
/*** fin boucle reconnaissance parenthèses ***/
end;
/*** fin boucle reconnaissance parenthèses et ratio ***/
run;
 
 
proc print DATA=c;run;
la sortie

Code :
1
2
3
4
5
6
7
8
 
            Obs               calcul               motif    denom                         calcul_old              atome
 
              1     45/(2-5/(2*6-(9/(8))+3:[8]))             8                      45/(2-5/(2*6-(9/8)+3/8))         4
              2     45/(2-5/(2*6-(9:[8])+3:[8]))             8                      45/(2-5/(2*6-(9/8)+3/8))         4
              3     45/(2-5/(2*6-[9:[8]]+3:[8]))     9/8                            45/(2-5/(2*6-(9/8)+3/8))         4
              4     45/(2-5:[2*6-[9:[8]]+3:[8]])             2*6-(9/8)+3/8          45/(2-5/(2*6-(9/8)+3/8))         4
              5     45:[2-5:[2*6-[9:[8]]+3:[8]]]             2-5/(2*6-(9/8)+3/8)    45/(2-5/(2*6-(9/8)+3/8))         4

Enfin j'ai beaucoup compliqué par rapport à ta situation du post précédent, j'ai peut-être compliqué inutilement, mais c'est comme ça que ça m'est venu pour décortiquer proprement le texte.

Peut-être suffisait-t-il de faire un tranwrd tout simple sur les ) pour enlever les duplications à la fin.
A toi de voir.
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 30
Vieux 20/12/2011, 19h23   #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
une modification

je te conseille de remplacer

Code :
parenthese_elementaire=prxparse('s/(.*[^\/])(\()([^\(\)]*)(\))(.*)/$1[$3]$5/');
par

Code :
parenthese_elementaire=prxparse('s/(.*[^\/]|^)(\()([^\(\)]*)(\))(.*)/$1[$3]$5/');
Le rajout |^ permet de tenir compte des parenthèses en début de chaine qui n'étaient pas gérée à cause de [^\/] (pour qu'il y ai reconnaissance il fallait qu'il y ai au moins un caractère différent de / devant la parenthèse ce qui n'est pas le cas dans le cas d'une chaine commençant par une parenthèse)

le |^ indique 'ou début de chaine' '|'=ou et '^'=debut de chaine

Edit : correction (.*[^\/|^]) en (.*[^\/]|^)
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 21h16   #6
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
Edit : mauvais post
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 22h46   #7
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
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
DATA a;
ratio='(5/6)+(9/(8-7))';output;
run;
DATA b;
SET a;
retain noyau_denom;
IF _n_=1 then do;
noyau_denom=prxparse('s/(.*)(\/)(.*)/$1|$3|$5/');end;
t=prxmatch(noyau_denom,ratio);
denom=translate(' '!!strip(prxposn(noyau_denom,3,ratio))!!' ','/','|');
modif=prxchange(noyau_denom,1,ratio);
output;
Do i= 1 TO 10;
test=INDEX(ratio,'/');
IF test then do;
ratio=modif;
noyau_denom=prxparse('s/(.*)(\/)(.*)/$1|$3|$5/');
t=prxmatch(noyau_denom,ratio);
denom=translate(' '!!strip(prxposn(noyau_denom,3,ratio))!!' ','/','|');
modif=prxchange(noyau_denom,1,ratio);
output;
end;
else i=100001;
end;
run;
Autre problème, par exemple pour l'expression: (5/6)+(9/(8-7))
il donne le résultat : (8-7)) et 6)+(9/(8-7)) à la place de (8-7) et 6
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/12/2011, 23h26   #8
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
Bonsoir,
c'est bien avec toi on fait des nocturnes

J'obtiens ceci

Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
              Obs    calcul                          motif      denom                  calcul_old
 
               1     45/(2-5/(2*6-(9/(8))+3:[8]))               8                      45/(2-5/(2*6-(9/8)+3/8))
               2     45/(2-5/(2*6-(9:[8])+3:[8]))               8                      45/(2-5/(2*6-(9/8)+3/8))
               3     45/(2-5/(2*6-[9:[8]]+3:[8]))    9/8                               45/(2-5/(2*6-(9/8)+3/8))
               4     45/(2-5:[2*6-[9:[8]]+3:[8]])               2*6-(9/8)+3/8          45/(2-5/(2*6-(9/8)+3/8))
               5     45:[2-5:[2*6-[9:[8]]+3:[8]]]               2-5/(2*6-(9/8)+3/8)    45/(2-5/(2*6-(9/8)+3/8))
               6     (5/(6))+(9:[8-7])                          8-7                    (5/6)+(9/(8-7))
               7     (5:[6])+(9:[8-7])                          6                      (5/6)+(9/(8-7))
               8     (5:[6])+[9:[8-7]]               9/(8-7)                           (5/6)+(9/(8-7))
               9     [5:[6]]+[9:[8-7]]               5/6                               (5/6)+(9/(8-7))
avec ce code

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
54
55
56
57
58
59
 
DATA a;
length calcul $100;
calcul='45/(2-5/(2*6-(9/8)+3/8))';output;
calcul='(5/6)+(9/(8-7))';output;
run;
 
 
DATA c;
SET a;
length motif $100 denom $100 calcul_old $100;
retain parenthese_elementaire ratio_et_parenthese ratio_atome sup_ratio_atome;
DROP  parenthese_elementaire ratio_et_parenthese ratio_atome t sup_ratio_atome;
IF _n_=1 then do;
ratio_atome=prxparse("s/(.*\/)([^\(\)\/\-\+\*]+)(.*)/$1($2)$3/");
parenthese_elementaire=prxparse('s/(.*[^\/]|^)(\()([^\(\)]*)(\))(.*)/$1[$3]$5/');
ratio_et_parenthese=prxparse('s/(.*)(\/\()([^\(\)\/]*)(\))(.*)/$1:[$3]$5/');
sup_ratio_atome=prxparse("s/(.*\/)(\()([^\(\)\/\-\+\*]+)(\))(.*)/$1$3$5/");
end;
calcul_old=calcul;
/***** remplace les forme du type 8/5 par 8/(5) / 2/A par 2/(A) etc...  ***/
t=prxmatch(ratio_atome,calcul);
do until (t=0);
call prxchange (ratio_atome,-1,calcul);
t=prxmatch(ratio_atome,calcul);
end;
/***** fin transformation  ***/
/*** boucle reconnaissance parenthèses et ratio ***/
do while (prxmatch(ratio_et_parenthese,calcul)=1 OR prxmatch(parenthese_elementaire,calcul)=1);
/*** boucle reconnaissance ratio ****/
do while (prxmatch(ratio_et_parenthese,calcul)=1);
denom=prxposn(ratio_et_parenthese,3,calcul);
motif='';
calcul=prxchange(ratio_et_parenthese,1,calcul);
denom=translate(denom,'()/','[]:');
       /**** suppression des "ratios atomes" 5/(8) --> 5/8 ***/
do while (prxmatch(sup_ratio_atome,denom));denom=prxchange(sup_ratio_atome,1,denom);end;
       /**** fin suppression des "ratios atomes" 5/(8) --> 5/8 ***/
output;
end;
/*** fin boucle reconnaissance ratio ***/
/*** boucle reconnaissance parenthèses ***/
do while (prxmatch(parenthese_elementaire,calcul)=1);
motif=prxposn(parenthese_elementaire,3,calcul);
denom='';
calcul=prxchange(parenthese_elementaire,1,calcul);
motif=translate(motif,'()/','[]:');
       /**** suppression des "ratios atomes" 5/(8) --> 5/8 ***/
do while (prxmatch(sup_ratio_atome,motif));motif=prxchange(sup_ratio_atome,1,motif);end;
       /**** fin suppression des "ratios atomes" 5/(8) --> 5/8 ***/
output;
end;
/*** fin boucle reconnaissance parenthèses ***/
end;
/*** fin boucle reconnaissance parenthèses et ratio ***/
run;
 
 
proc print DATA=c;run;
Ce n'est pas ce que tu veux ?

Parce que dans ton code l'expression régulière que l'on avait proposé dans un premier temps est trop "simpliste" je pense pour traiter ce que tu veux faire. Ca risque d'être compliqué d'obtenir ce que tu veux avec ton code actuel.

Je t'en propose un qui semble faire ce que tu veux et tu ne l'utilise pas, pour quelle raison ?
jerome_pdv2 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/12/2011, 00h00   #9
Candidat au titre de Membre du Club
 
Femme
Conseil - Consultant en systèmes d'information
Inscription : novembre 2011
Messages : 80
Détails du profil
Informations personnelles :
Sexe : Femme
Localisation : Maroc

Informations professionnelles :
Activité : Conseil - Consultant en systèmes d'information
Secteur : Conseil

Informations forums :
Inscription : novembre 2011
Messages : 80
Points : 12
Points : 12
Je l'utilise, merci Jerome, j'ai voulu juste mentionner que le bout de code que j'ai partagé ne prend po le cas général
aminao est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 21/12/2011, 00h17   #10
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
Ah ok, je pensais que tu étais toujours à la recherche de l'expression régulière qui ferait tout en un.

Cela étant dit, en réfléchissant je pense qu'il y a peut être moyen d'avoir une seule expression régulière à la place des 4.
Mais elle risque d'être très complexe à élaborer, et qui dit complexe, dit complexe a débugguer si elle marche pas, et donc, si on est pas un génie des regexp , beaucoup de temps...

Enfin il ya quelques experts sur le forum, peut-être viendront ils en donner une !

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



Fuseau horaire GMT +2. Il est actuellement 20h30.


 
 
 
 
Partenaires

Hébergement Web