模板工具包:从命令行将数组变量传递到 tpage?
template-toolkit: passing array variables into tpage from command line?
我可以正常使用此模板:
$ cat matrix.tt
[% DEFAULT
ncols = 3
elems = [1,2,3,4,5,6,7,8,9]
%]
\left[\begin{matrix}
[% WHILE elems.size %]
[% elems.splice(0,ncols).join(' & ') %]
[% IF elems.size %]\[% END %]
[% END %]
\end{matrix}\right]
$ tpage --pre_chomp --post_chomp matrix.tt
\left[\begin{matrix}1 & 2 & 3\4 & 5 & 6\7 & 8 & 9\end{matrix}\right]
但这不起作用:
$ tpage --define ncols=2 --define elems=[1,2,3,4] matrix.tt
undef error - WHILE loop terminated (> 1000 iterations)
我发现使用以下代码,使用 --define
选项将数组传递给 tpage
并非易事。
$ cat pk.tt
[% DEFAULT
ho = [1,2]
-%]
ho is [% ho %]
po is [% po %]
$ tpage --define po=[1,3] pk.tt #I want po to be interpreted as an array
ho is ARRAY(0x1a3fd00)
po is [1,3]
输出显示 po 是一个标量。我想从命令行传递数组,有什么办法吗?
根据数组中值的复杂程度,您也许可以摆脱这样的情况:
[%- el = elems.split(',') -%]
\left[\begin{matrix}
[% WHILE el.size %]
[% el.splice(0,ncols).join(' & ') %]
... #etc
$ tpage --define ncols=2 --define elems="1,2,3,4" matrix.tt
当然,如果 elems
不受控制,或者嵌入了可能导致痛苦的元字符或逗号。但除此之外,使用 .split()
VMethod.
将标量提升为数组就足够简单了
tpage
的命令行参数不会被评估为 Perl 代码,因此您只能获取字符串值。如果你想支持任意 Perl 代码,你必须破解 tpage
源代码。
在源代码中找到以下行:
my %ttopts = $config->varlist('^template_(?!directive_)', 1);
在下一行,添加以下代码:
foreach my $var (keys %{ $ttopts{variables} }) {
$ttopts{variables}{$var} = eval $ttopts{variables}{$var};
die $@ if $@;
}
这会遍历 --define
的所有参数并对其调用 eval
,将它们从字符串转换为 Perl 代码。
当你 运行 这样做时,请确保引用你的论点以防止它们被 shell:
扩展
$ ./tpage --define 'array=["foo","bar"]' --define 'hash={baz=>"qux"}' foo.tt
$VAR1 = [
'foo',
'bar'
];
$VAR1 = {
'baz' => 'qux'
};
$ cat foo.tt
[% USE Dumper %]
[% Dumper.dump(array) %]
[% Dumper.dump(hash) %]
要传递文字字符串,您必须用 q{}
或 qq{}
将其引用,因为 AppConfig 去除常规引号(tpage
在幕后使用 AppConfig 读取命令行参数)。例如:
$ ./tpage --define 'string=q{foo}' foo.tt
$VAR1 = 'foo';
$ cat foo.tt
[% USE Dumper %]
[% Dumper.dump(string) %]
请注意,尽管 Template Toolkit 支持几乎所有 Perl 类型的变量,但我修改后的 tpage
版本不支持。数字、字符串、数组和散列应该都可以工作;子程序没有。
这是一种从命令行将任何数据传递到 tpage
的方法,而无需调整 tpage
源或模板。
$ cat matrix.tt
[% DEFAULT
ncols = 3
elems = [1,2,3,4,5,6,7,8,9,10,11,12]
%]
\left[\begin{matrix}
[% WHILE elems.size %]
[% elems.splice(0,ncols).join(' & ') %]
[% IF elems.size %]\[% END %]
[% END %]
\end{matrix}\right]
$ cat <(echo '[% elems=["x","y","z",1,2,3] %]') matrix.tt |tpage --pre_chomp --post_chomp
\left[\begin{matrix}x & y & z\1 & 2 & 3\end{matrix}\right]
$
或者如果您愿意,您可以输入指令来设置变量,然后按 ^D:
$ rlwrap cat - matrix.tt |tpage --pre_chomp --post_chomp
[%
ncols=4
elems=[4,5,6,7,"x","y","z","t"]
%]
\left[\begin{matrix}4 & 5 & 6 & 7\x & y & z & t\end{matrix}\right]
$
rlwrap
保存您输入的行,并在以后按 up
键使它们可用。如果不需要,可以删除 rlwrap
。
如果 shell 支持这种重定向,该方法适用于任何可以处理 stdin
的程序。我希望它很便携。
我可以正常使用此模板:
$ cat matrix.tt
[% DEFAULT
ncols = 3
elems = [1,2,3,4,5,6,7,8,9]
%]
\left[\begin{matrix}
[% WHILE elems.size %]
[% elems.splice(0,ncols).join(' & ') %]
[% IF elems.size %]\[% END %]
[% END %]
\end{matrix}\right]
$ tpage --pre_chomp --post_chomp matrix.tt
\left[\begin{matrix}1 & 2 & 3\4 & 5 & 6\7 & 8 & 9\end{matrix}\right]
但这不起作用:
$ tpage --define ncols=2 --define elems=[1,2,3,4] matrix.tt
undef error - WHILE loop terminated (> 1000 iterations)
我发现使用以下代码,使用 --define
选项将数组传递给 tpage
并非易事。
$ cat pk.tt
[% DEFAULT
ho = [1,2]
-%]
ho is [% ho %]
po is [% po %]
$ tpage --define po=[1,3] pk.tt #I want po to be interpreted as an array
ho is ARRAY(0x1a3fd00)
po is [1,3]
输出显示 po 是一个标量。我想从命令行传递数组,有什么办法吗?
根据数组中值的复杂程度,您也许可以摆脱这样的情况:
[%- el = elems.split(',') -%]
\left[\begin{matrix}
[% WHILE el.size %]
[% el.splice(0,ncols).join(' & ') %]
... #etc
$ tpage --define ncols=2 --define elems="1,2,3,4" matrix.tt
当然,如果 elems
不受控制,或者嵌入了可能导致痛苦的元字符或逗号。但除此之外,使用 .split()
VMethod.
tpage
的命令行参数不会被评估为 Perl 代码,因此您只能获取字符串值。如果你想支持任意 Perl 代码,你必须破解 tpage
源代码。
在源代码中找到以下行:
my %ttopts = $config->varlist('^template_(?!directive_)', 1);
在下一行,添加以下代码:
foreach my $var (keys %{ $ttopts{variables} }) {
$ttopts{variables}{$var} = eval $ttopts{variables}{$var};
die $@ if $@;
}
这会遍历 --define
的所有参数并对其调用 eval
,将它们从字符串转换为 Perl 代码。
当你 运行 这样做时,请确保引用你的论点以防止它们被 shell:
扩展$ ./tpage --define 'array=["foo","bar"]' --define 'hash={baz=>"qux"}' foo.tt
$VAR1 = [
'foo',
'bar'
];
$VAR1 = {
'baz' => 'qux'
};
$ cat foo.tt
[% USE Dumper %]
[% Dumper.dump(array) %]
[% Dumper.dump(hash) %]
要传递文字字符串,您必须用 q{}
或 qq{}
将其引用,因为 AppConfig 去除常规引号(tpage
在幕后使用 AppConfig 读取命令行参数)。例如:
$ ./tpage --define 'string=q{foo}' foo.tt
$VAR1 = 'foo';
$ cat foo.tt
[% USE Dumper %]
[% Dumper.dump(string) %]
请注意,尽管 Template Toolkit 支持几乎所有 Perl 类型的变量,但我修改后的 tpage
版本不支持。数字、字符串、数组和散列应该都可以工作;子程序没有。
这是一种从命令行将任何数据传递到 tpage
的方法,而无需调整 tpage
源或模板。
$ cat matrix.tt
[% DEFAULT
ncols = 3
elems = [1,2,3,4,5,6,7,8,9,10,11,12]
%]
\left[\begin{matrix}
[% WHILE elems.size %]
[% elems.splice(0,ncols).join(' & ') %]
[% IF elems.size %]\[% END %]
[% END %]
\end{matrix}\right]
$ cat <(echo '[% elems=["x","y","z",1,2,3] %]') matrix.tt |tpage --pre_chomp --post_chomp
\left[\begin{matrix}x & y & z\1 & 2 & 3\end{matrix}\right]
$
或者如果您愿意,您可以输入指令来设置变量,然后按 ^D:
$ rlwrap cat - matrix.tt |tpage --pre_chomp --post_chomp
[%
ncols=4
elems=[4,5,6,7,"x","y","z","t"]
%]
\left[\begin{matrix}4 & 5 & 6 & 7\x & y & z & t\end{matrix}\right]
$
rlwrap
保存您输入的行,并在以后按 up
键使它们可用。如果不需要,可以删除 rlwrap
。
如果 shell 支持这种重定向,该方法适用于任何可以处理 stdin
的程序。我希望它很便携。