OVH Cloud OVH Cloud

traitement de chaines avec parenthèses imbriquées

5 réponses
Avatar
dizzounette
Bonjour,
Je suis encore assez débutante avec Perl, donc je vous demande de
m'excuser pour les bétises que je pourrais dire.

Je cherche à traiter des chaînes de caractères de la forme :

texte1 convert(partie1 , partie2) texte2

Je souhaite obtenir :

texte1 CAST(partie2 AS partie1) texte2

texte1 et texte2 sont variables et peuvent même contenir des
parenthèses et des virgules
partie1 contient du texte parfois suivi de (1ou2chiffres)
partie2 peut contenir du texte et eventuellement 1 ou plusieurs
niveaux de parentèses (mais chaque parenthèse ouvrante possède sa
parentèse fermante).

Je détecte la premère parenthèse grâce au mot clef "convert" mais je
n'arrive pas à detecter la fin de la fonction (juste parès partie2).

Je ne sais vraiment pas comment m'y prendre pour arriver à effectuer
cette transformation. En fouillant les archives et les sites web j'ai
vu des réferences à un module nomé Test::Balanced mais je n'arrive pas
à m'en sortir pour mon cas
J'espère que l'un de vous pourras m'aider

Virginie

5 réponses

Avatar
Benoit Izac
Bonjour,

le 17/05/2004 à 13:25, (virginie) a écrit
dans le message :

Bonjour,
Je suis encore assez débutante avec Perl, donc je vous demande de
m'excuser pour les bétises que je pourrais dire.

Je cherche à traiter des chaînes de caractères de la forme :

texte1 convert(partie1 , partie2) texte2

Je souhaite obtenir :

texte1 CAST(partie2 AS partie1) texte2

texte1 et texte2 sont variables et peuvent même contenir des
parenthèses et des virgules
partie1 contient du texte parfois suivi de (1ou2chiffres)
partie2 peut contenir du texte et eventuellement 1 ou plusieurs
niveaux de parentèses (mais chaque parenthèse ouvrante possède sa
parentèse fermante).

Je détecte la premère parenthèse grâce au mot clef "convert" mais je
n'arrive pas à detecter la fin de la fonction (juste parès partie2).

Je ne sais vraiment pas comment m'y prendre pour arriver à effectuer
cette transformation. En fouillant les archives et les sites web j'ai
vu des réferences à un module nomé Test::Balanced mais je n'arrive pas
à m'en sortir pour mon cas
J'espère que l'un de vous pourras m'aider


essaye ça :

s/convert(s*([^,]+?)s*,s*(S+)s*)/CAST($2 AS $1)/;

--
Benoit Izac

Avatar
dizzounette
Tout d'abbord, désolée de ne pas poster corrctement dans le thread
mais Google-Groups fait des siennes.

Je crois que je me suis malheureusement mal exprimée et que par
conséquent il est difficile de me donner une réponse bien adaptée.

Je vais donc essayer de clarifier les choses. Voici donc des exemples
concrets qui seront peut-être plus facile à compredre que mon
explication vaseuse.

'Adresse'= ltrim(convert(varchar(10),an_num_voie)+' ') +
ltrim(an_nom_voie),
deviendra =>
'Adresse'= ltrim(CAST(an_num_voie AS varchar(10))+' ') +
ltrim(an_nom_voie),

pour ça, la ligne s/convert(s*([^,]+?)s*,s*(S+)s*)/CAST($2 AS
$1)/; marche

Mais on peut également avoir des lignes du type :
'Adresse'= convert(varchar(10),ltrim(an_nom_voie))
qui deviendra =>
'Adresse'= CAST(ltrim(an_nom_voie) AS varchar(10))


Il est même possible dans la partie2 d'avoir des expressions encore
plus complexes comportant même des espaces.

convert(int,(isnull(variable1,0) * 100)/isnull(variable2,1))
qui deviendra =>
CAST((isnull(variable1,0) * 100)/isnull(variable2,1) AS int)


C'est donc pour ce type de cas qu'il est plus difficile de traiter la
ligne car les parenthèses des fonctions imbriquées rendent le travail
plus complexe.

Merci

Virginie


Je cherche à traiter des chaînes de caractères de la forme :
texte1 convert(partie1 , partie2) texte2
Je souhaite obtenir :
texte1 CAST(partie2 AS partie1) texte2

texte1 et texte2 sont variables et peuvent même contenir des
parenthèses et des virgules
partie1 contient du texte parfois suivi de (1ou2chiffres)
partie2 peut contenir du texte et eventuellement 1 ou plusieurs
niveaux de parentèses (mais chaque parenthèse ouvrante possède sa
parentèse fermante).

Je détecte la premère parenthèse grâce au mot clef "convert" mais je
n'arrive pas à detecter la fin de la fonction (juste parès partie2).

Je ne sais vraiment pas comment m'y prendre pour arriver à effectuer
cette transformation. En fouillant les archives et les sites web j'ai
vu des réferences à un module nomé Text::Balanced mais je n'arrive pas
à m'en sortir pour mon cas


Avatar
Rue des Prairies
virginie wrote:
Tout d'abbord, désolée de ne pas poster corrctement dans le thread
mais Google-Groups fait des siennes.

Je crois que je me suis malheureusement mal exprimée et que par
conséquent il est difficile de me donner une réponse bien adaptée.

Je vais donc essayer de clarifier les choses. Voici donc des exemples
concrets qui seront peut-être plus facile à compredre que mon
explication vaseuse.

'Adresse'= ltrim(convert(varchar(10),an_num_voie)+' ') +
ltrim(an_nom_voie),
deviendra =>
'Adresse'= ltrim(CAST(an_num_voie AS varchar(10))+' ') +
ltrim(an_nom_voie),

pour ça, la ligne s/convert(s*([^,]+?)s*,s*(S+)s*)/CAST($2 AS
$1)/; marche

Mais on peut également avoir des lignes du type :
'Adresse'= convert(varchar(10),ltrim(an_nom_voie))
qui deviendra =>
'Adresse'= CAST(ltrim(an_nom_voie) AS varchar(10))


Il est même possible dans la partie2 d'avoir des expressions encore
plus complexes comportant même des espaces.

convert(int,(isnull(variable1,0) * 100)/isnull(variable2,1))
qui deviendra =>
CAST((isnull(variable1,0) * 100)/isnull(variable2,1) AS int)


C'est donc pour ce type de cas qu'il est plus difficile de traiter la
ligne car les parenthèses des fonctions imbriquées rendent le travail
plus complexe.

Merci

Virginie



Je cherche à traiter des chaînes de caractères de la forme :
texte1 convert(partie1 , partie2) texte2
Je souhaite obtenir :
texte1 CAST(partie2 AS partie1) texte2

texte1 et texte2 sont variables et peuvent même contenir des
parenthèses et des virgules
partie1 contient du texte parfois suivi de (1ou2chiffres)
partie2 peut contenir du texte et eventuellement 1 ou plusieurs
niveaux de parentèses (mais chaque parenthèse ouvrante possède sa
parentèse fermante).

Je détecte la premère parenthèse grâce au mot clef "convert" mais je
n'arrive pas à detecter la fin de la fonction (juste parès partie2).

Je ne sais vraiment pas comment m'y prendre pour arriver à effectuer
cette transformation. En fouillant les archives et les sites web j'ai
vu des réferences à un module nomé Text::Balanced mais je n'arrive pas
à m'en sortir pour mon cas



Bonjour,

Il y a surement plus simple :

$str = 'convert(int,(isnull(variable1,0) * 100)/isnull(variable2,1)) +
ltrim(variable3)';

$str =~ s/convert/CAST/;
while($str =~ /([()])/gc) {
$poso[$ouv++] = pos($str)-1 if($1 eq '(');
$posf[$fer++] = pos($str)-1 if($1 eq ')');
if($ouv eq $fer) {
$str1 = substr($str, $poso[0], $posf[$fer-1]-$poso[0]+1);
last;
}
}
($var1 = $str1) =~ s/((w*),(.*))/($2 AS $1)/;
substr($str, $poso[0], $posf[$fer-1]-$poso[0]+1) = $var1;
print $str;


Olivier.


Avatar
Benoit Izac
Bonjour,

le 19/05/2004 à 10:17, (virginie) a écrit
dans le message :

[...]
Il est même possible dans la partie2 d'avoir des expressions encore
plus complexes comportant même des espaces.

convert(int,(isnull(variable1,0) * 100)/isnull(variable2,1))
qui deviendra =>
CAST((isnull(variable1,0) * 100)/isnull(variable2,1) AS int)


C'est donc pour ce type de cas qu'il est plus difficile de traiter la
ligne car les parenthèses des fonctions imbriquées rendent le travail
plus complexe.


Je ne suis pas sûr que Perl soit le plus adapté pour ce que tu veux
faire. C'est néanmoins possible :

#!/usr/bin/perl -w
use strict;
my $pe;
$pe = qr{((?:(?>[^()]+)|(??{ $pe }))*)};
my $motif = qr/convert$pe/;

while (<DATA>) {
print;
while (/($motif)/) {
my $old = $1;
my $new = $old;
$new =~ s/convert(s*([^,]+?)s*,s*(.+?)s*)$/CAST($2 AS $1)/;
s/Q$oldE/$new/;
}
print "$_n";
}
__DATA__
texte1 convert(partie1 , partie2) texte2
texte1 convert(partie1,()()() ) texte2
texte1 convert(jdshqèa"'_çreazi()() dqs dfjsd , kfk(dk)f) texte2
'Adresse'= ltrim(convert(varchar(10),an_num_voie)+' ') + ltrim(an_nom_voie),
'Adresse'= convert(varchar(10),ltrim(an_nom_voie))
convert(int,(isnull(variable1,0) * 100)/isnull(variable2,1))


J'ai honteusement pompé le « $pe = ... » dans la 3ème édition de
« Programmation en Perl ». Ça permet une recherche récursive pour
vérifier que les parenthèses sont bien appariées ; ici, utilisé via
« convert$pe », ça conserve la fonction convert() complète.

--
Benoit Izac

Avatar
dizzounette
Benoit Izac wrote in message news:...
Je ne suis pas sûr que Perl soit le plus adapté pour ce que tu veux
faire. C'est néanmoins possible :


Et bien pour ce cas particulier, Perl n'est peut-être pas la solution
la plus adapté mais pour tout le reste du traitement de mes fichiers,
ça va très bien :-) et j'ai déjà bien avancé donc ça m'aurais embeté
de recommencer.

#!/usr/bin/perl -w
use strict;
my $pe;
$pe = qr{((?:(?>[^()]+)|(??{ $pe }))*)};
my $motif = qr/convert$pe/;

while (<DATA>) {
print;
while (/($motif)/) {
my $old = $1;
my $new = $old;
$new =~ s/convert(s*([^,]+?)s*,s*(.+?)s*)$/CAST($2 AS $1)/;
s/Q$oldE/$new/;
}
print "$_n";
}


Merci beaucoup :-) ça marche impec :-)

J'ai honteusement pompé le « $pe = ... » dans la 3ème édition de
« Programmation en Perl ». Ça permet une recherche récursive pour
vérifier que les parenthèses sont bien appariées ; ici, utilisé via
« convert$pe », ça conserve la fonction convert() complète.


"Honteusement" : pas tellement. J'ai ce livre mais comme je n'ai pas
encore le niveau, je n'arrive pas toujours à trouver les soltutions à
mes problèmes car je ne sais pas toujours par où les aborder et quoi
chercher (c'est un beau pavé quand même : donc quand on sait pas ce
qu'on cherche...)