开发者

"for" loop inside a Text::Template template

开发者 https://www.devze.com 2023-03-03 14:27 出处:网络
I\'m trying to use perl Text::Template for s开发者_如何学运维hort templates and so far failed to get it to iterate over an array.

I'm trying to use perl Text::Template for s开发者_如何学运维hort templates and so far failed to get it to iterate over an array.

Here is a short test program I wrote to demonstrate what I'm trying to do:

#!/usr/bin/perl
use Text::Template;
my $template = Text::Template->new(TYPE => 'STRING', SOURCE => <<'__EOT__');
array[0]: { $array[0] }
{ foreach my $i (@array) { }
 {$i}
}
__EOT__
print $template->fill_in(HASH => { array => [qw(item1 item2)]});

According to the Text::Template manual I expected this to print: array[0]: item1 item1 item2 But instead it prints array[0]: item1

(i.e. the output of the first line outside the loop and an empty line).

I couldn't find anywhere on the web any example of someone actually using a loop inside a template, though the documentation says it should "just work".

What am I missing?


my $template = Text::Template->new(TYPE => 'STRING', SOURCE => <<'__EOT__',  DELIMITERS => [qw(<% %>)],);

Pick different delimiters. The documentation advises you to do so several times for various reasons, mostly for being easier to work with because Perl code also uses {} braces. It also says:

Because the parsing of templates is simplified by the absence of backslash escapes, using alternative DELIMITERS may speed up the parsing process by 20-25%. This shows that my original choice of { and } was very bad.

Just {$i} does not work here because it is in void context. The documentation says:

The result of the last statement executed will be evaluted in scalar context; the result of this statement is a string, which is interpolated into the template in place of the program fragment itself.

Rewrite it with the $OUT variable:

<% foreach my $i (@array) {
    $OUT .= $i
} %>

The documentation says:

Anything you append to this variable will appear in the output of the template. Also, if you use $OUT in a program fragment, the normal behavior, of replacing the fragment with its return value, is disabled; instead the fragment is replaced with the value of $OUT.

<% $OUT .= $_ for @array %>

Same result, but shorter.


A couple of experiments indicate that this:

{ stuff }

Is turned into (effectively) something like this pseudo-perl:

my $x = eval(stuff);
$template =~ s/{ stuff }/$x/;

So the "stuff" needs to be an expression so that it returns something to put into the template. Your "stuff" is a foreach loop which doesn't have a value so your template doesn't do anything interesting.

If you look at the tests for Text::Template (always go to the test suite for examples, the test suites for CPAN packages are invaluable for learning how things work), you'll see things like this:

{ $t = ''; foreach $n (1 .. 20) { $t .= $n . ' ' } $t }

Note the way $t is being used. That indicates that you want something more like this for your template:

array[0]: { $array[0] }
{ $t = ''; foreach my $i (@array) { $t .= "\t$i\n" } }

There's also the $OUT special variable which can take the place of $t above. The documentation for CPAN packages is generally pretty good and well worth reading, you'll miss it when you work in other languages.

0

精彩评论

暂无评论...
验证码 换一张
取 消