使用区域设置编译指示设置区域设置

时间:2017-03-07 08:38:57

标签: perl locale

我正在尝试从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"应该足以覆盖命令行(外部环境设置)。这里发生了什么?

1 个答案:

答案 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:词法声明您要使用特定于语言环境的排序, 和运行时操作以选择所需的语言环境。