Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I was hoping to use a simple approach to replace Perl variables in html templates such as:
... <h1> $title </h1> ...
So first reaction was to do something like $template_file_string =~ s/(\$\w+)/$$1/g; Cool i thought, but this does not work. So I resorted to eval'ing the file string, however that presents a HUGE security hole since if the file contained something like "; rm -rf * ;" Yikes.... It is even more dangerous if the data was coming from user input! So right now I am replacing ";" with "\;". But there must be a better way.

Replies are listed 'Best First'.
Re: symbolic references in reg exp
by jerji (Novice) on Mar 18, 2000 at 03:48 UTC
    You want Text::Template. It handles this sort of thing quite nicely. If you are curious about implementation details of such a task, just read the source.
Re: symbolic references in reg exp
by btrott (Parson) on Mar 18, 2000 at 03:48 UTC
    It doesn't work because your regex is wrong. If you *really* wanted to do it using symbolic references, you'd want to use something like:
    $template_file_string =~ s/\$(\w+)/${$1}/g;
    See the difference? You were matching "$title", then trying to substitute that with the value of the variable "$$title"--but that's not what you wanted. You want to just match the word part of the variable name ("title"), then substitute the whole thing with the value of "$title".

    *However*, don't do it this way--there are better ways. One way is to put your template values into a hash, with the keys being the template variable names, and the values being the values that you want to substitute for the template variables; then use a regex to do the substitution.

    my %vars = ( title => 'Foo Bar' ); my $template = q(<h1>$title</h1>); $template =~ s/\$(\w+)/$vars{$1}/eg;
    Another (very) good option would be to use Text::Template.
    use Text::Template; my %vars = ( title => "Foo Bar" ); my $t = new Text::Template(TYPE => 'STRING', SOURCE => q(<h1>{$title}< +/h1>)) or die "Couldn't construct template: $Text::Template::ERROR"; my $text = $t->fill_in(HASH => \%vars);
    This last is probably the most robust and extensible approach, so check it out. (Note that you have to slightly modify your template so that your variables are in '{}'.)
Re: symbolic references in reg exp
by PipTigger (Hermit) on Mar 18, 2000 at 04:37 UTC
    I may be a bit of a square since I'm still shy of modules and all the object notation ... which means I can't comment on the greatness or robustness of Text::Template however I have written several cgi scripts that utilize the aforementioned hash lookup for template points to be replaced by the associated value and since this method doesn't eval the replacement text, it remains just text and therefore pretty harmless to the server... it could pretty easily embed nasty java for the client but AFAIK it's not going to be able to do anything from your server other than spit out verbatim in html. Maybe this is redundant. Maybe this is redundant. So please forgive me. TTFN & Shalom.

    -PipTigger
Even I know that one!
by Anonymous Monk on Mar 18, 2000 at 05:34 UTC
    ${$1}
Re: symbolic references in reg exp
by Anonymous Monk on Mar 18, 2000 at 13:13 UTC
    Ok this is someone else who wrote his own itty bitty language before he knew about Text::Template

    I just went through the perldoc on it and this would be great, it'd make my main part of one the programs much cleaner and the huge loop would go away..

    except it's just not that simple for me. Basically what I have in my syntax is something like #PIC#, etc. However, where there is a #PIC#, I don't want just the same pic every where that #PIC# is placed, they have to be different ones. Text::Template can't help me specify different $pics would it? I couldn't find it in perldoc
    what would be really cool if Text::Template could call a user defined function that would return what to replace it with.. or something like that. But alas, I can not find this functionality
      I'll just add {get_pic} and it'll call get_pic and i'll have get_pic return the desired stuff :)

      Man I love perl modules.
Re: symbolic references in reg exp
by Anonymous Monk on Mar 18, 2000 at 07:37 UTC
    btrott Thank for the info: BTW, I had tried $template_file_string =~ s/\$(\w+)/${$1}/g; And that did not work either, however your $template =~ s/\$(\w+)/$vars{$1}/eg; slightly modified as $template =~ s/\$(\w+)/$main::{$1}/eg; Achieved the desired results.