使用 Perl 尊重区域设置进行排序

使用 Perl 尊重区域设置进行排序

以下数据需要根据区域设置排序顺序进行排序:

wird
sin
wär
pêche
war
Über
Uber
péché
peach

使用也没有问题sort

$ sort < data
peach
pêche
péché
sin
Uber
Über
war
wär
wird

尊重语言环境,并且

$ LC_ALL=C sort < data
Uber
peach
péché
pêche
sin
war
wird
wär
Über

没有语言环境。

现在我尝试这样做perl,但失败了:

$ perl -e 'local $/ = undef; print sort <>;' < data
Über
pêche
war
péché
sin
Uber
peach
wär
wird

结果要么是排序的第一个输出,要么是第二个输出。

运行 Ubuntu 12.04 LTS

答案1

问题是local $/ = undef。它会导致perl将整个文件读入@ARGV数组,这意味着它仅包含一个元素,因此sort无法对其进行排序(因为您正在对仅包含一个元素的数组进行排序)。我希望输出必须与您的开始数据相同(我也使用Ubuntu 12.04 LTS, perl version 5.14.2

$ perl -le 'local $/ = undef;print ++$i for <>' < cat
1

$ perl -le 'print ++$i for <>' < cat
1
2
3
4
5
6
7
8
9

如果删除local $/ = undef,perlsort将与 shell 产生相同的输出sort with LC_ALL=C

$ perl -e 'print sort <>' < data
Uber
peach
péché
pêche
sin
war
wird
wär
Über

笔记

如果没有use locale,则perl忽略您当前的区域设置。 Perl 比较运算符("lt", "le", "cmp", "ge", and "gt")使用LC_COLLATE(当LC_ALL不存在时),并且sort也会受到影响,因为它cmp默认使用。

您可以获取当前LC_COLLATE值:

$ perl -MPOSIX=setlocale -le 'print setlocale(LC_COLLATE)'
en_US.UTF-8

答案2

因为将文件读入数组的正确方法是:

$ perl -e 'print sort <>;' < data

设置输入记录分隔符to undef 只是将整个文件放入一个标量中。那么对单值数组进行排序并没有多大意义。

阵列模式已经可以一次性读取整个文件。那么排序就有意义了:

$ perl -e 'use locale; print sort <>;' < data
peach
péché
pêche
sin
Uber
Über
war
wär
wird

在这里,我的ENVIRONMENTLANG=en_US.UTF-8。如果没有该use locale;语句,您将使用默认LC_ALL=C排序方案。

如果您想了解更多:

相关内容