Perl Template Toolkit - Preprocess шаблоны обратно в скрипт Perl

Простите, если этот вопрос уже был задан и / или дан ответ в другом месте.

Прежде чем я начну, я должен указать, что природа этого запроса может не требовать добавления кода в эту ветку, скорее ответом может быть просто ссылка на документацию модуля Template Toolkit с комментарием "ПРОЧИТАЙТЕ ЭТО СНОВА":). Чтобы быть еще более ясным, я согласился бы на краткий ответ ДА ​​или НЕТ.

Допустим, у меня есть работающий Perl-скрипт, который обрабатывает шаблоны Template::Toolkit без проблем.

Но один из моих шаблонов содержит "имена" (имена людей, имена серверов, в конце концов это действительно не имеет значения: только "имена"). Эти имена используются для создания FILENAMES, содержащих обработанные данные позже.

Сегодня у меня это работает через следующий псевдокод:

$template->process('names.tt','output.txt');

Затем я беру сгенерированный список "имен" в "output.txt" и помещаю их в массив в том же исполняемом скрипте Perl. Этот список затем используется итеративным способом для вывода данных, указанных в другом шаблоне, и присваивает имя каждому результирующему файлу на основе исходного "имени":

foreach(@names){
   my $filename = $_ . '.txt';
   $template->process('profile_doc.tt',$filename)
}

Как я уже сказал, все это прекрасно работает (на самом деле идеально). Моя проблема в том, что он наполняет мой код без необходимости (нужно управлять открытыми FH и т. Д.). Должен быть лучший путь, учитывая необычайные способности ТТ.

Поэтому я начал читать о включенных модулях Template::Toolkit (например, STASH, PROVIDER и т. Д.). Я понимаю, что STASH, например, позволяет вам вводить данные в существующий объект модуля шаблона дополнительным способом, однако это является противоположностью того, что я хочу сделать.

Мой фактический вопрос (опять же, ДА или НЕТ, было бы просто замечательно как ответы с точки зрения того, возможно ли это):

Возможно ли для сценария Perl прочитать шаблон, скажем, такой, который содержит объект HASH, хранящийся в Template-Toolkit, и создать новый HASH, который будет использоваться фактическим сценарием Perl (например, вне шаблона)?

Если бы это было возможно, это исключило бы необходимость извлечения данных в запутанном виде из одного шаблона и использования этих данных для обработки другого шаблона. Скорее я теоретически мог бы сделать следующее без необходимости вручную заполнять список, который нужно записать на диск, а затем снова прочитать через FH.

foreach(sort keys $derivedhash{obj}){
   $filename = $_->{name} . '.txt';
   $template->process('profile_doc.tt',$_->{name});
}

Спасибо, пожалуйста, поймите, что я приложил все усилия, чтобы создать пригодную для использования псевдомодель, поскольку реальный код включает в себя конфиденциальные элементы и, к сожалению, исключает раскрытие. Я надеюсь, вы поймете. Я могу предоставить другие "очищенные абстракции / примеры" по мере необходимости.

ОБНОВИТЬ

В ответ на пользователя икегами:

Во-первых, спасибо за ответ.

Хорошо, давайте начнем с одного из ваших комментариев: " ... который не имеет смысла, так как TT не хранит хэши"... Хм.... Если мы не говорим о двух разных вещах, это неправильно, как я делаю это сегодня.. например, вот размещенный в шаблоне объект, который содержит элементы начального хэша, о которых я говорил:

[%- SERVERS = [
      {entry={
              NAME => 'Server1'
              SERIAL => '1234567890'
              DESC => 'A file server'
      }}
      {entry={
              NAME => 'Server2'
              SERIAL => '0987654321'
              DESC => 'An account server'
      }}
]-%]

Еще раз, вышеупомянутое работает, и оно существует в TT..........., и, если я не ошибаюсь, вышесказанное, безусловно, выглядит, чувствует и чувствует себя как хэш.... Я даю вам, тем не менее, то, что он заключен в массив... так что, возможно, это не 100% -ный "чистый объект HASH" класса A, но я, конечно, действительно использую его как хэш (и, что очень приятно, тоже).

Прежде чем вы что-то скажете, я уже понимаю, что мне, скорее всего, потребуется обновить имена ключей, чтобы они были УНИКАЛЬНЫМИ для простоты анализа (сами по себе ключи хеш-функции должны быть уникальными), но это отдельная попытка.

Вы были правы, когда сказали: "Это явно не то, что вы хотели спросить". Позвольте мне прояснить окончательный вопрос, как вы и просили:

Может ли Template Toolkit из исполняемого сценария Perl прочитать "Шаблон 1", который содержит один объект HASH (как описано выше), и прочитать упомянутую структуру HASH в новый хеш-объект, который существует только внутри указанного исполняющего скрипта (в отличие от сам шаблон)? Этот "новый хеш" в конечном итоге будет использоваться для имен файлов, сгенерированных "шаблоном 2".

Наконец, чтобы удовлетворить ваш последний запрос:

Выше приведен отрывок ввода, который вы запрашивали. Вывод, который мне нужен, будет настоящим Perl-хешем, полученным из данных внутри вызываемого шаблона.

Так что в качестве эквивалента Perl (желаемый выход):

%newhash = (
    entry => {
        NAME => "Server1",
        SERIAL => "1234567890",
        DESC => "A file server"
    },
    .... other entries ....
);

.... будет использоваться для "подачи" определенных значений, скажем, значений "NAME", в другие шаблоны, обработанные "позже".

Надеюсь это прояснит путаницу... еще раз спасибо икегами...

2 ответа

Ради того, чтобы принять решение, я подумал, что покажу код, который использует JSON модуль для загрузки некоторых данных из файла на диске

Предположим, мой файл data.json содержит это (взято из ваших собственных данных образца)

servers.json

[
  {
    "NAME"   : "Server1",
    "SERIAL" : "1234567890",
    "DESC"   : "A file server"
  },
  {
    "NAME"   : "Server2",
    "SERIAL" : "0987654321",
    "DESC"   : "An account server"
  }
]

Затем я могу написать этот код Perl, чтобы открыть и прочитать данные в массив хэшей Perl, например так:

servers.pl

use strict;
use warnings 'all';
use v5.10.1;
use autodie;

use JSON;

use constant JSON_FILE => 'servers.json';

my $servers = do {
    open my $fh, '<:raw', JSON_FILE;
    local $/;
    decode_json <$fh>;
};

use Data::Dump;

dd $servers;

выход

[
  { DESC => "A file server", NAME => "Server1", SERIAL => 1234567890 },
  { DESC => "An account server", NAME => "Server2", SERIAL => "0987654321" },
]

Обратите внимание, что я использовал autodie прагма, чтобы избежать необходимости вручную проверять статус open вызов. autodie Впервые был сделан основной модуль в Perl версии 5.10.1, поэтому я тоже этого потребовал

decode_json Вызов принимает только строку в формате JSON, поэтому я использовал do блок, чтобы открыть и прочитать файл и декодировать содержимое, отбрасывая все временные значения, такие как дескриптор файла и строку JSON

Data::Dump это только для того, чтобы показать форму структуры данных, прочитанной в

Данные JavaScript (JSON) очень похожи на эквивалентный Perl, за исключением следующего

  • в Perl => заменяется на :
  • Допускаются только двойные кавычки, без одинарных кавычек
  • Хеш-ключи, а также строковые значения должны быть заключены в кавычки
  • Последний элемент списка может не иметь запятой

Но нет необходимости помещать кавычки вокруг числового литерального значения. Он работает так же, как Perl, так что, если вы хотите сохранить числовую строку с начальным нулем, вам нужно будет использовать кавычки, в противном случае пустое число хорошо

Я верю, что обратный процесс - написание файла JSON - очевиден. Ссылка на структуру данных Perl должна быть передана encode_json создать строку JSON, которая затем записывается в файл обычным способом

Если вы отчаянно нуждаетесь в большей скорости кодирования и декодирования, тогда есть JSON::XS модуль, который частично написан на C и, следовательно, гораздо быстрее, однако любой JSON-модуль будет работать намного быстрее, чем все, что вы могли бы установить с помощью Template Toolkit. Вариант XS представляет собой замену чистой версии Perl в отношении encode_json а также decode_json

ТТ производит текст. Но если бы TT генерировал текстовое представление хеша, было бы легко создать хеш из него.

Шаблон:

[%- USE Template.Plugin.JSON -%]
[%- SERVERS = [ ... ] -%]
[%- SERVERS.json -%]

Код:

use JSON qw( from_json );

$template->process('template.tt', {}, \my $json)
   or die(...);

my $servers = from_json($json);

Я использовал JSON, но подойдут и любые другие способы сериализации и десериализации структуры данных.


Тем не менее, я совершенно не понимаю, почему вы хотите это сделать. Вы даже не можете воспользоваться преимуществами функций TT таким образом!

Если бы смысл был в том, чтобы использовать возможности TT для изменения структуры данных, то создание самого шаблона JSON имело бы гораздо больше смысла. Например,

[
   [% IF devel %]
      {
         "entry": {
            "NAME":   "Server1-devel",
            "SERIAL": "1234567890",
            "DESC":   "Development server"
         }
      },
   [% ELSE %]
      {
         "entry": {
            "NAME":   "Server1-prod",
            "SERIAL": "1234567891",
            "DESC":   "Production server"
         }
      },
   [% END %]
   ...
]

use JSON qw( from_json );

my %vars = (
   devel => ...,
);

$template->process('template.tt', \%vars, \my $json)
   or die(...);

my $servers = from_json($json);

Кстати, если у вас есть хеш с одним постоянным ключом, вы делаете что-то не так.

[
   { entry => { NAME => "Server1", SERIAL => 1234567890, DESC => "A file server" } },
   { entry => { NAME => "Server2", SERIAL => "0987654321", DESC => "An account server" } },
]

должно быть

[
   { NAME => "Server1", SERIAL => 1234567890, DESC => "A file server" },
   { NAME => "Server2", SERIAL => "0987654321", DESC => "An account server" },
]

или же

{
   "Server1" => { SERIAL => 1234567890, DESC => "A file server" },
   "Server2" => { SERIAL => "0987654321", DESC => "An account server" },
}
Другие вопросы по тегам