Perl 模板工具包';s somevar.substr()和UTF-8
我们在Catalyst应用程序中使用模板工具包。我们将TT配置为使用UTF-8,以前没有任何问题 现在我调用string变量的substr()方法。不幸的是,它在n个字节后而不是n个字符后分割字符串。如果第n个字节和(n+1)个字节生成unicode字符,则会将其拆分,并且只有第1个字节是substr()结果的一部分 如何纠正或解决该行为?Perl 模板工具包';s somevar.substr()和UTF-8,perl,encoding,utf-8,substr,template-toolkit,Perl,Encoding,Utf 8,Substr,Template Toolkit,我们在Catalyst应用程序中使用模板工具包。我们将TT配置为使用UTF-8,以前没有任何问题 现在我调用string变量的substr()方法。不幸的是,它在n个字节后而不是n个字符后分割字符串。如果第n个字节和(n+1)个字节生成unicode字符,则会将其拆分,并且只有第1个字节是substr()结果的一部分 如何纠正或解决该行为? [% string = "fööbär"; string.length; # prints 9 string.substr(0, 5); # print
[% string = "fööbär";
string.length; # prints 9
string.substr(0, 5); # prints "föö" (1 ascii + 2x 2 byte unicode)
string.substr(0, 4): # prints "fö?" (1 ascii, 1x 2 byte unicode, 1 unknown char)
%]
到目前为止,我们对Unicode字符没有任何问题,它们既不来自数据库,也不来自模板中的文本
编辑:这是我在我的Catalyst应用程序中配置Catalyst::View::TT
模块的方式:
__PACKAGE__->config(
# DEBUG => DEBUG_ALL,
DEFAULT_ENCODING => 'utf-8',
INCLUDE_PATH => My::App->path_to( 'root', 'templates' ),
TEMPLATE_EXTENSION => '.tt',
WRAPPER => "wrapper/default.tt",
render_die => 1,
);
Wikipedia关于UTF-8的文章提供了一个表格,显示了非ASCII字符的使用情况。该表说明了UTF-8的以下简单规则:
- 如果字节的最高位为0,则该字节表示ASCII字符
- 如果一个字节的两个最高位为11,则这是多字节字符的开始,从最高顺序位开始的连续1位数表示多字节字符中的字节总数。因此,位表示为110xxxxx的字节是2字节字符的开头,1110xxxx是3字节字符的开头,11110xxx是4字节字符的开头。(您可以忽略假设的5字节和6字节字符,因为Unicode仅限于21位字符集而不是32位字符集。)
- 如果一个字节的两个最高位是10,则该字节是多字节字符的一部分(但不是该字符的第一个字节)
string.length
和string.substring()
,但以字符而不是字节为单位
更新:问题没有指定所使用的编程语言,我也不知道“模板工具包”暗示了Perl的使用。一旦我意识到这一点,我在谷歌上搜索了一下,发现您的问题可能是因为需要在源代码中添加
use utf8
指令。您可以找到关于这一点的讨论。关于UTF-8的Wikipedia文章提供了一个表格,显示了非ASCII字符的使用情况。该表说明了UTF-8的以下简单规则:
- 如果字节的最高位为0,则该字节表示ASCII字符
- 如果一个字节的两个最高位为11,则这是多字节字符的开始,从最高顺序位开始的连续1位数表示多字节字符中的字节总数。因此,位表示为110xxxxx的字节是2字节字符的开头,1110xxxx是3字节字符的开头,11110xxx是4字节字符的开头。(您可以忽略假设的5字节和6字节字符,因为Unicode仅限于21位字符集而不是32位字符集。)
- 如果一个字节的两个最高位是10,则该字节是多字节字符的一部分(但不是该字符的第一个字节)
string.length
和string.substring()
,但以字符而不是字节为单位
更新:问题没有指定所使用的编程语言,我也不知道“模板工具包”暗示了Perl的使用。一旦我意识到这一点,我在谷歌上搜索了一下,发现您的问题可能是因为需要在源代码中添加
use utf8
指令。您可以找到关于这一点的讨论。答案非常简单(用Perl),幸运的是:
use Encode qw{encode decode};
其工作方式是将Unicode字符串解码为Perl字符串,然后可以按预期的方式使用substr()和length(),然后再次对其进行编码以供输出
使用该标题:
# $unicodeString = 'fööbär';
my $perlString = decode('UTF-8', $unicodeString);
printf "%d\n", length($perlString); # should be 6
printf "%s\n", substr($perlString, 0, 3); # should be 'föö'
# whatever other processing you want here with $perlString . . .
# Then, you want to reencode that back to a proper UTF-8 string:
my $unicodeString = encode('UTF-8', $perlString);
这会有帮助吗?答案很简单(在Perl中),幸运的是:
use Encode qw{encode decode};
其工作方式是将Unicode字符串解码为Perl字符串,然后可以按预期的方式使用substr()和length(),然后再次对其进行编码以供输出
使用该标题:
# $unicodeString = 'fööbär';
my $perlString = decode('UTF-8', $unicodeString);
printf "%d\n", length($perlString); # should be 6
printf "%s\n", substr($perlString, 0, 3); # should be 'föö'
# whatever other processing you want here with $perlString . . .
# Then, you want to reencode that back to a proper UTF-8 string:
my $unicodeString = encode('UTF-8', $perlString);
这会有帮助吗?我使用Perl 1.12.2对MSWin32模板模块进行了快速测试。 它可以正确处理所有这些substr操作 这是我的测试代码:
use Template;
# some useful options (see below for full list)
my $config = {
# DEFAULT_ENCODING => 'utf-8',
INCLUDE_PATH => 'd:/devel/perl', # or list ref
INTERPOLATE => 1, # expand "$var" in plain text
EVAL_PERL => 1, # evaluate Perl code blocks
};
# create Template object
my $template = Template->new($config);
# define template variables for replacement
my $vars = {
var1 => "abcdef"
};
# specify input filename, or file handle, text reference, etc.
my $input = 'ttmyfile.txt';
# process input template, substituting variables
print $template->process($input, $vars);
ttmyfile.txt
Var = [% var1 %]
[% string = "fööbär" -%]
[% string.length %] # prints 6
[% string.substr(0, 5) %] # prints "fööbä"
[% string.substr(0, 4) %] # prints "fööb"
输出:
Var = abcdef
6 # prints 6
fööbä # prints "fööbä"
fööb # prints "fööb"
1
即使没有使用utf8
或默认编码
,所有这些都可以正常工作。这里的重点是:
.tt
文件编码为UTF8。这是一项必须完成的任务!因为模板工具包是根据BOM检测Unicode文件编码的
- 您可以使用Windows记事本保存带有BOM表的文件,只需执行
-->file
-->编码:“UTF-8”李>save
- 通过输入
和set fenc=utf8
,您也可以使用VIM制作,然后保存文件,文件将以BOM开头李>set bomb
NCODING
参数Template->new({NCODING=>'utf-8'})代码>作为“utf-8”将强制模板
以“utf-8”的形式加载模板文件
因为
Catalyst::View::TT
依赖于模板,所以我相信它也应该可以工作!祝你好运~~~我用Perl1.12.2对MSWin32模板模块进行了快速测试。
它可以正确处理所有这些substr操作
这是我的测试代码:
use Template;
# some useful options (see below for full list)
my $config = {
# DEFAULT_ENCODING => 'utf-8',
INCLUDE_PATH => 'd:/devel/perl', # or list ref
INTERPOLATE => 1, # expand "$var" in plain text
EVAL_PERL => 1, # evaluate Perl code blocks
};
# create Template object
my $template = Template->new($config);
# define template variables for replacement
my $vars = {
var1 => "abcdef"
};
# specify input filename, or file handle, text reference, etc.
my $input = 'ttmyfile.txt';
# process input template, substituting variables
print $template->process($input, $vars);
ttmyfile.txt
Var = [% var1 %]
[% string = "fööbär" -%]
[% string.length %] # prints 6
[% string.substr(0, 5) %] # prints "fööbä"
[% string.substr(0, 4) %] # prints "fööb"
输出:
Var = abcdef
6 # prints 6
fööbä # prints "fööbä"
fööb # prints "fööb"
1
即使没有使用utf8
或默认编码
,所有这些都可以正常工作。关键的事情