我正在尝试从Perl脚本中覆盖默认的区域设置。首先,我尝试从Bash shell命令行执行覆盖:
p.pl
#! /usr/bin/env perl
use feature qw(say);
use strict;
use warnings;
my @data = qw( A a B b C c );
{
use locale;
say join ', ', sort @data;
}
运行此脚本时,我可以通过设置变量LC_ALL
来覆盖命令行中的当前语言环境:
$ LC_ALL=C p.pl
A, B, C, a, b, c
$ LC_ALL=en_US.UTF-8 p.pl
a, A, b, B, c, C
但是,如果我在Perl脚本中覆盖它不起作用:
p2.pl :
use feature qw(say);
use strict;
use warnings;
BEGIN {
$ENV{LC_ALL} = "C";
}
my @data = qw( A a B b C c );
{
use locale;
say join ', ', sort @data;
}
当我运行p2.pl
时,它没有给我LC_ALL=C
排序顺序:
$ LC_ALL=en_US.UTF-8 p2.pl
a, A, b, B, c, C
它仍然提供en_US.UTF-8
排序顺序。我认为设置$ENV{LC_ALL}="C"
应该足以覆盖命令行(外部环境设置)。这里发生了什么?
答案 0 :(得分:1)
使用区域设置模块,您可以使用setlocale
功能更改区域设置。但请注意,它默认导出并可能影响其他程序。不要在线程中使用它。
对于排序,使用LC_COLLATE可能更好,LC_ALL会影响所有区域设置,这可能不需要。
#!/usr/bin/perl -w
use strict;
use POSIX qw(locale_h);
use locale;
my $old_locale = setlocale(LC_COLLATE);
my @data = qw( A a B b C c );
print join ', ', sort @data;
print "\n";
# change current locale
setlocale(LC_COLLATE, "C");
print join ', ', sort @data;
print "\n";
# reset back to default
setlocale(LC_COLLATE, "");
有关详细信息,请参阅setlocale documentation。
进一步解释(source):
因为locale pragma不是运行时动作,因为setlocale()是。 该pragma是一个词法范围的声明。 pragma的效果 就是那里,有一个locale-using和locale-ignoring变种 操作,将使用locale-using变体。字符串比较 默认情况下,排序使用是一种操作。
在调用locale-using操作的情况下,其行为受到影响 当前的语言环境。这不是词汇决定的静态属性 操作,但运行时全局变量。这是libc的模型 Perl正在暴露的语言环境。语言环境很早就初始化了 在执行中,以环境变量推荐的方式。 libc模型是后来环境变量的变化 不会自动更改某个地区。可以设置当前区域设置 在程序控制下,以匹配新的环境设置或以某种方式 与环境无关,但如果没有该计划,它永远不会改变 请求。因此,您在程序执行期间设置环境变量 (即使在BEGIN块中)也不会改变当前的语言环境。
所以你需要做两件事来获得你正在寻找的语言环境效果 for:词法声明您要使用特定于语言环境的排序, 和运行时操作以选择所需的语言环境。