execution de code par la fonction EVAL

execution de code par la fonction EVAL - Perl - Programmation

Marsh Posté le 09-06-2005 à 11:17:55    

Bonjour,
 
Je dois actuellement reecrire un programme perl qui fait de la traduction de format de fichier text. Seulement les regles de traduction differ en fonction des differents formats de données en entrée.
Pour cela le programme contient dans un fichier de configuration en XML les differentes regles de transformation sont sous forme de code PERL comme par exemple:
 

<FORMULA>my @customer_tag_tmp=split(/#/,[#e2001c]"|1|"
);my $quality_tmp; if (defined($customer_tag_tmp[4])) { $quality_tmp=$customer_tag_tmp[4]; } else { $quality_tmp = ""; };$quality_tmp;
</FORMULA>  
[/#000ef0]
 
Le champ |1| est remplacer par ma variable a utilisé avant execution de la regle.
 
$formule =~ s/\|1\|/$data/g;
 
L'execution de ce code est fait par l'intermediaire de la fonction eval
$output_data = eval($formule);
 
Je voulais savoir, sachant que la quantité de données est assez important, si l'execution de code oar l'intermediaire de EVAL prennais du temps et chargeait le system ???
Je voulais savoir aussi, si il etait possible pour eviter d'utiliser EVAL, de crée de maniere dynamique au demarrage du programme un module PERL qui regrouperai mes differentes regles en fonctions, ces dernieres seraient appelées au lieu d'être evalué comme par exemple:
 
sub formula_1{
my $val = shift;
my @customer_tag_tmp=split(/#/,"$val" );
my $quality_tmp;  
if (defined($customer_tag_tmp[4])) { $quality_tmp=$customer_tag_tmp[4]; } else { $quality_tmp = ""; };
return $quality_tmp;
}
 
Merci d'avance

Reply

Marsh Posté le 09-06-2005 à 11:17:55   

Reply

Marsh Posté le 09-06-2005 à 13:54:06    

ce que tu peux faire c'est effectivement creer une fonction à la volée kand tu la vois, qui prenne comme parametres les valeurs de |1|, |2|, ...
 
en gors:

Code :
  1. use Digest::MD5 "md5";
  2. # transforme '|x|' en '$_[x-1]' (sans virer les " )
  3. $formule =~ s/\|(\d+)\|/'$_['.($1-1).']'/gse;
  4. # on recupere un petit identifiant sur 16 octets
  5. my $formula_id = md5($formula);
  6. # la fonction existe t elle deja en cache?
  7. # sinon on l'evalue en en faisant une sub anonyme (sub{...})
  8. # le test se fait avec le ||=
  9. # on evite ainsi de rééavluer des fonction deja connues
  10. $CacheSub{$formula_id} ||= eval ('sub {'.$formula.'}');
  11. # utilisation de la fonction
  12. $CacheSub{$formula_id}->(@data)


 

Reply

Marsh Posté le 09-06-2005 à 14:03:24    

Tu veux dire que je n'ai meme pas a construire de module specifique.
Je peux mettre en memoire une fonction en l'evaluant une seule fois a l'ignitialisation. Et apres je l'appel comme je veux avec les arguments.
Si cela marche je te remercie beaucoups.

Reply

Marsh Posté le 09-06-2005 à 14:19:28    

J'ai un petit soucis.
J'utilise un USE STRICT dans mon programme et l'evaluation ne veux pas se faire.
Message:
Can't use string ("substr("$_[0]",0,16);" ) as a subroutine ref while "strict refs" in use at
 
J'ai essayer en rajoutant:
 eval ('sub { my @var = @_;'.$formula.'}');
 
en ayant remplacer $[x]_ par uen variable declaré de type tableau. mais cela ne change rien.

Reply

Marsh Posté le 09-06-2005 à 14:46:59    

J'ai essaye de mettre dans ma boucle de creation l'instruction
no strict 'refs';
Mais cela ne change rien

Reply

Marsh Posté le 09-06-2005 à 15:11:06    

Pour information la formule en question est egale a:
 
<FORMULA>substr("|1|",0,16);</FORMULA>

Reply

Marsh Posté le 09-06-2005 à 16:03:40    

chez moi ceci marche:

Code :
  1. my $a = 'substr("|1|",0,16)';
  2. $a =~ s/"\|(\d+)\|"/'$_['.($1-1).']'/gse;
  3. $b = eval("sub{$a}" );
  4. print $b->("123456789012345678901234567890" );


 
ca affichier bien "1234567890123456";

Reply

Marsh Posté le 09-06-2005 à 16:34:20    

Merci cela fonctionne.
J'avais une coquille dans mon code du coup j'essayais d'executer $a->() au lieux de $b->().
 
Cela fonctionne super bien j'ai gagné enormement en performance.

Reply

Marsh Posté le 09-06-2005 à 16:36:41    

de rien

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed