Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

lost in eval and regexp

by lepetitalbert (Monsignor)
on Nov 21, 2007 at 14:17 UTC ( #652135=perlquestion: print w/ replies, xml ) Need Help??
lepetitalbert has asked for the wisdom of the Perl Monks concerning the following question:

Hi dear Monks

As I'd like to create a easy to install cgi script ( no HTML::Template), I try to write a very simple 'replace' sub, to load a html and replace some variables.

sub replace { my $file = shift; open FILE , $file or die "oups"; my @BUFFER = <FILE> and close FILE; my @OUT_BUFFER; foreach my $line ( @BUFFER ) { if ( $line =~ /~~/ ) { my @SPLITTED = split( /~~/ , $line ); foreach ( @SPLITTED ) { if ( $_ =~ /\$/ ){ my $tmp = eval $_; $line =~ s/~~\$.*~~/$tmp/; } } } push ( @OUT_BUFFER , $line ); } print @OUT_BUFFER; }

this works with :

~~$french_month_name{$month}~~ 20~~$year~~ </td> <td colspan="2" align="right"> <div id="date"> ~~$today_day_name~~ ~~$today_day_display_number~~ ~~$french_month_name{$today_month_numb +er}~~ &nbsp; </div> </td> </tr> <tr> <td class="titlebar1"> </td> <td class="titlebar2" width="80px" align="righ +t"> <a class="white" href="~~$cgi_dir~~ /agenda.pl?user= ~~$user~~&month= ~~$prev_month~~&year= ~~$down_link_year_num~~"> &raquo; ~~$french_month_name{$prev_mon +th}~~ &nbsp; </a> <td class="titlebar2" width="80px" align="righ +t"> <a class="white" href="~~$cgi_dir~~ /agenda.pl?user= ~~$user~~&month= ~~$next_month~~&year= ~~$up_link_year_num~~"> &raquo; ~~$french_month_name{$next_mon +th}~~ &nbsp; </a> </td> </tr> </table> </div>

but not with

<div class="cell ~~$cell~~" style="background-colo +r : #f9f9f9"> <div class="date"> &nbsp; ~~$day_prev_month~~ </div> </div>

And I don't understand why.

The replace sub is in a loop, maybe an out of scope problem ?

If somebody has the exact regexp for ~~$year~~ and ~~$french_month_name{$month}~~ ?

And if somebody has a solution I could use multiple ~~*~~ on one line

Thank you and ...

Have a nice day

"There is only one good, namely knowledge, and only one evil, namely ignorance." Socrates

Comment on lost in eval and regexp
Select or Download Code
Re: lost in eval and regexp
by gamache (Friar) on Nov 21, 2007 at 14:38 UTC
    This works:
    while ($str =~ s/~~(\$.+?)~~/__TOKEN__/) { my $val = eval $1; $str =~ s/__TOKEN__/$val/; }
    There is probably a more efficient way to do it, but this does the job. $str can be each individual line, or whole chunks of the HTML.

    Update: a better way, as suggested by ikegami...

    $str =~ s/~~(\$.+?)~~/eval $1/ge;
    I wonder how s///e evaded my notice for so long.
      Let's hope your variables don't contain "~~"! Use s///eg instead of this double-substitution while loop.
Re: lost in eval and regexp
by toolic (Chancellor) on Nov 21, 2007 at 14:44 UTC
    It is not clear to me what you are trying to accomplish since you do not provide any expected output. However, if I run your code using the strictures (use warnings; use strict;), I get many warnings of the variety:
    Use of uninitialized value in concatenation (.) or string
    If I add print "tmp=$tmp\n"; after your eval statement, I see that $tmp is the culprit. So, I believe your eval statement is not doing what you expect it to do. What do you expect it to do?
Re: lost in eval and regexp
by ikegami (Pope) on Nov 21, 2007 at 15:00 UTC

    You should really really really really really really use an existing template module. You would have installed and learned it in the time it took you to get this question answered. Converting your templates over isn't all that hard either.

    sub convert { my ($template_name) = @_; my $template; { open my $fh, '<', $template_name or die("Unable to open template file \"$template_name\": $!\ +n"); local $/; $template = <$fh>; } $template =~ s/~~\$(.+?)~~/... new syntax .../g; { open my $fh, '>', $template_name or die("Unable to overwrite template file \"$template_name\" +: $!\n"); print $fh $template; } }

    At the very least, pass your variables in a hash. That will get rid of the eval EXPR and solve all scoping problems.

    sub replace { my ($template_name, $params) = @_; my $template; { open my $fh, '<', $template_name or die("Unable to open template file \"$template_name\": $!\ +n"); local $/; $template = <$fh>; } $template =~ s/~~\$(.+?)~~/ if (exists($params->{$1})) { if (defined($params->{$1})) { $params->{$1} } else { warn("Template file \"$template_name\" references undefine +d variable $params->{$1}\n"); '' } } else { warn("Template file \"$template_name\" references non-existin +g variable $params->{$1}\n"); '' } /eg; print("$template\n"); } my %params = ( cell => ..., day_prev_month => ..., ); replace($template_name, \%params);

      Dear Monks,

      Thank you gamache, will try that immediatly

      Good point toolic, here's the output od the first template :

      novembre 2007 </td> <td colspan="2" align="right"> <div id="date"> Mercredi 21 novembre &nbsp; </div> </td> </tr> <tr> <td class="titlebar1"> </td> <td class="titlebar2" width="80px" align="righ +t"> <a class="white" href="/cgi-bin/inlook /agenda.pl?user= &month= 10&year= 07"> &raquo; octobre &nbsp; </a> <td class="titlebar2" width="80px" align="righ +t"> <a class="white" href="/cgi-bin/inlook /agenda.pl?user= &month= 12&year= 07"> &raquo; décembre &nbsp; </a> </td> </tr> </table> </div>

      ikegami, as I agree with you totally, that's what I did first with Html::Template. But the goal of the game is to keep the installaion of the script as simple as 'upload ,run'. And sorry, I was unable to find the regexp :)

      Thank you fellow Monks

      And have a nice day

      "There is only one good, namely knowledge, and only one evil, namely ignorance." Socrates

        What about "upload,unzip,run"? Templating systems are usually Pure Perl, so there's no installation requirement other than having the files handy.

        You may need the following at the top of your script in order to tell Perl where to look for the modules. Note that only core modules are used.

        use File::Spec::Functions qw( rel2abs ); use File::Basename qw( dirname ); use lib dirname(rel2abs($0));

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://652135]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (6)
As of 2014-12-22 07:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (112 votes), past polls