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

Monks, I am in need of some enlightenment on this problem. I have a string $tmpl, which contains $vars which I wish to have interpolated into said string upon printing. I haven't been able to find the right syntax to do this. Here's my non-working attempt:

#!/usr/local/bin/perl use strict; my $name = "Fred"; my @infile = <DATA>; my $tmpl = join '', @infile; # output print $tmpl; __DATA__ This is my template. Here is my $name

which spits out:

This is my template. Here is my $name

And what I'd like is "...Here is my Fred"

-------------------------------------
Nothing is too wonderful to be true
-- Michael Faraday

Replies are listed 'Best First'.
Re: Interpolating $var in a $string
by perrin (Chancellor) on May 27, 2004 at 17:45 UTC
Re: Interpolating $var in a $string
by dragonchild (Archbishop) on May 27, 2004 at 17:56 UTC
    Use a real templating system. Look at HTML::Template or Template Toolkit. Those are the most commonly used.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

    I shouldn't have to say this, but any code, unless otherwise stated, is untested

      This is, of course, the clean, proper, readable and maintainable way to do it. I was looking for a quick and dirty hack.

      Cheers

      -------------------------------------
      Nothing is too wonderful to be true
      -- Michael Faraday

Re: Interpolating $var in a $string
by pizza_milkshake (Monk) on May 27, 2004 at 17:54 UTC
    there's probably a module that will do this nicely, but here's ghetto hack way
    #!perl -w use strict; my %vars = qw(name Fred); my $tmpl = do { local $/; <DATA> }; $tmpl =~ s/\$([a-zA-Z_]\w*)/$vars{$1}/ge; print $tmpl; __DATA__ This is my template. Here is my $name

    perl -e"\$_=qq/nwdd\x7F^n\x7Flm{{llql0}qs\x14/;s/./chr(ord$&^30)/ge;print"

Re: Interpolating $var in a $string
by eclark (Scribe) on May 27, 2004 at 18:05 UTC

    This is fraught with danger, dont do this, use a template system like Text::Template, Template Toolkit, or something similar. But here's what you're trying to do.

    #!/usr/bin/perl -w use strict; my $name = "Fred"; my @infile = <DATA>; my $tmpl = join '', @infile; # output print eval("qq{${tmpl}}"); __DATA__ This is my template. Here is my $name

    Be warned, you can create a huge security hole by doing this.

Re: Interpolating $var in a $string
by ChrisR (Hermit) on May 27, 2004 at 17:47 UTC
    While there may be a better way to do this, I just added a simple regex:
    #!/usr/local/bin/perl use strict; my $name = "Fred"; my @infile = <DATA>; my $tmpl = join '', @infile; $tmpl =~ s/\$name/$name/g; # output print $tmpl; __DATA__ This is my template. Here is my $name
Re: Interpolating $var in a $string
by RandomMonkey (Initiate) on May 27, 2004 at 18:37 UTC
    Here is a simple solution.

    #!/usr/local/bin/perl use strict; my $name = "Fred"; s/(\$\w+)/$1/eeg foreach my @infile = <DATA>; my $tmpl = join '', @infile; # output print $tmpl; __DATA__ This is my template. Here is my $name
Re: Interpolating $var in a $string
by qq (Hermit) on May 27, 2004 at 20:22 UTC

    People often think that the templating systems are all heavyweight. They're not. See Text::MicroMason among many others.

    qq

Re: Interpolating $var in a $string
by dimar (Curate) on May 28, 2004 at 02:43 UTC

    Try the reverse approach to fully leverage the power of perl

    Here's something to consider ... instead of loading a template string into your perl script that has some data, why not load the data into your perl script that has some template string? It's just as quick and dirty, it obviates the need to use a Templating module (if you're opposed to that) and it's still relatively 'readable' for a simple fill-in-the-blank type document. For example:

    ### INIT pragma and lib use strict; use warnings; use YAML; ### INIT vars my $sRaw = join '', (<DATA>); my $d = YAML::Load($sRaw)->{data}[0]; ### OUTPUT template print q% This is my template. I am %.$d->{fname}.q% %.$d->{lname}.q%, %.$d->{job}.q%. I own %.$d->{assets}.q%. Dont be a *@#!! You can make big $$bucks$$ by writing template code!! %; __DATA__ data: - fname: Elmer J. lname: Fudd job: millionaire assets: a mansion and a yacht

    Your interpolated vars look like this:

    %.$d->{foo}.q%
    It's a bit more typing than just ...
    $foo
    but less of a security risk, and the 'q' operator will not interpolate *anything* except your interpolated vars. This is nice when you have an output template that includes funky metacharacters or anything else that might trip up your script. Also, you don't have to use the percent symbol, you can use any character that you know will never appear in your output template.

    When you think about it, it's rather silly to write "template munging code" ... because perl already does that quite well! Instead, focus on "data munging code" ...
    There's a million possible data formats out there.
    There's a multitude of ways to fill in a template (otherwise why would you generalize it into a template to begin with?).
    There's a million ways to get data into a perl script, and you can make them interchangeable without having to change a single line of your template string.

    Just some bits to consider