Цикл for для шаблона Text::Template
Я пытаюсь использовать perl Text::Template для коротких шаблонов и пока не смог заставить его перебирать массив.
Вот короткая тестовая программа, которую я написал, чтобы продемонстрировать, что я пытаюсь сделать:
#!/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)]});
В соответствии с руководством Text::Template я ожидал, что это будет печатать: массив [0]: item1 item1 item2 Но вместо этого он печатает массив [0]: item1
(т.е. вывод первой строки вне цикла и пустой строки).
Я не смог найти в Интернете ни одного примера, когда кто-нибудь действительно использовал цикл внутри шаблона, хотя в документации сказано, что он должен "просто работать".
Что мне не хватает?
2 ответа
my $template = Text::Template->new(TYPE => 'STRING', SOURCE => <<'__EOT__', DELIMITERS => [qw(<% %>)],);
Выберите разные разделители. Документация советует вам делать это несколько раз по разным причинам, в основном из-за того, что с ними легче работать, потому что в Perl-коде также используется {}
брекеты. Это также говорит:
Поскольку синтаксический анализ шаблонов упрощается благодаря отсутствию обратной косой черты, использование альтернативных разделителей может ускорить процесс синтаксического анализа на 20-25%. Это показывает, что мой первоначальный выбор {и} был очень неудачным.
Просто {$i}
не работает здесь, потому что это в пустом контексте. В документации сказано:
Результат последнего выполненного оператора будет оцениваться в скалярном контексте; Результатом этого оператора является строка, которая вставляется в шаблон вместо самого фрагмента программы.
Перепишите его с помощью $OUT
переменная:
<% foreach my $i (@array) {
$OUT .= $i
} %>
В документации сказано:
Все, что вы добавляете в эту переменную, будет отображаться в выходных данных шаблона. Также, если вы используете $OUT во фрагменте программы, нормальное поведение замены фрагмента его возвращаемым значением отключается; вместо этого фрагмент заменяется значением $OUT.
<% $OUT .= $_ for @array %>
Тот же результат, но короче.
Пара экспериментов показывает, что это:
{ stuff }
Превращается (эффективно) во что-то вроде этого псевдоперла:
my $x = eval(stuff);
$template =~ s/{ stuff }/$x/;
Таким образом, "материал" должен быть выражением, чтобы он возвращал что-то в шаблон. Ваш "материал" является foreach
цикл, который не имеет значения, поэтому ваш шаблон не делает ничего интересного.
Если вы посмотрите на тесты для Text::Template
(всегда заходите в набор тестов для примеров, наборы тестов для пакетов CPAN неоценимы для изучения того, как все работает), вы увидите такие вещи:
{ $t = ''; foreach $n (1 .. 20) { $t .= $n . ' ' } $t }
Обратите внимание на способ $t
используется. Это означает, что вы хотите что-то более похожее на этот шаблон:
array[0]: { $array[0] }
{ $t = ''; foreach my $i (@array) { $t .= "\t$i\n" } }
Там также $OUT
специальная переменная, которая может заменить $t
выше. Документация для пакетов CPAN, как правило, довольно хорошая и заслуживает прочтения, вы пропустите ее, когда будете работать на других языках.