我需要从文件中对行进行排序,保存为UTF-8。这些行可以以西里尔字母或拉丁字符开头。我的代码在西里尔字母上运行错误。
sub sort_by_default {
my @sorted_lines = sort {
$a <=> $b
||
fc( $a) cmp fc($b)
} @_;
}
答案 0 :(得分:10)
与cmp
一起使用的sort
对此无效;它没有编码的概念,只是通过代码点,逐个字符,以及许多语言中的惊喜进行比较。使用Unicode::Collate。†通过tchrist和this post更多地了解this post以及更多perl.com article。
另一个问题是正确读取(解码)utf8中的输入和写入(编码)输出。确保处理标准流数据的一种方法是通过open pragma,您可以使用Encode::decode设置“层”,以便在读取/写入数据时对输入和输出进行解码/编码。
总而言之,一个例子
use warnings;
use strict;
use feature 'say';
use Unicode::Collate;
use open ":std", ":encoding(UTF-8)";
my $file = ...;
open my $fh, '<', $file or die "Can't open $file: $!";
my @lines = <$fh>;
chomp @lines;
my $uc = Unicode::Collate->new();
my @sorted = $uc->sort(@lines);
say for @sorted;
模块的cmp
方法可用于个别比较(如果是数据)
是一个复杂的数据结构,而不仅仅是一个扁平的行列表,例如)
my @sorted = map { $uc->cmp($a, $b) } @data;
需要适当设置$a
和$b
,以便从@data
中提取要比较的内容。
如果您在源代码中有utf8数据,则需要use utf8
,而如果您通过其他渠道(包括@ARGV
)收到utf8,则可能需要手动perlmonks post这些字符串。
请参阅链接的帖子(及其中的链接)和文档以获取更多详细信息。有关详细信息,请参阅此EffectivePerler article。有关自定义排序,请参阅此{{3}}。
†示例:通过代码点比较ä
&gt; b
,而德语中接受的订单为ä
&lt; b
perl -MUnicode::Collate -wE'use utf8; binmode STDOUT, ":encoding(UTF-8)";
@s = qw(ä b);
say join " ", sort { $a cmp $b } @s; #--> b ä
say join " ", Unicode::Collate->new->sort(@s); #--> ä b
'
因此我们需要使用Unicode::Collate
(或自定义排序例程)。
答案 1 :(得分:2)
要打开保存为UTF-8的文件,请使用适当的图层:
open my $FH, '<:encoding(UTF-8)', 'filename' or die $!;
不要忘记为输出设置相同的图层。
#! /usr/bin/perl
use warnings;
use strict;
binmode *DATA, ':encoding(UTF-8)';
binmode *STDOUT, ':encoding(UTF-8)';
print for sort <DATA>;
__DATA__
Борис
Peter
John
Владимир
答案 2 :(得分:1)
在Perl中正确处理UTF-8的关键是确保Perl知道信息的某个源或目标是UTF-8。根据您获取信息的方式不同,这样做会有所不同。如果UTF-8来自输入文件,则打开文件的方式是:
open( my $fh, '<:encoding(UTF-8)', "filename" ) or die "Cannot open file: $!\n";
如果您要在脚本源中包含UTF-8,请确保您拥有:
use utf8;
在剧本的开头。
如果您要从STDIN
获取UTF-8字符,请在脚本开头使用此字符:
binmode(STDIN, ':encoding(UTF-8)');
STDOUT
使用:
binmode(STDOUT, ':encoding(UTF-8)');
另外,请务必阅读UTF-8 vs. utf8 vs. UTF8以了解每个编码名称之间的区别。 utf8
或UTF8
将允许有效的UTF-8和无效的UTF-8(根据第一个UTF-8提议的标准),并且不会抱怨无效的代码点。 UTF-8
将允许有效的UTF-8,但不允许无效的代码点组合;它是utf-8-strict
的简称。您还可以阅读问题How do I sanitize invalid UTF-8 in Perl?
。
最后,在@zdim建议后,您可以在脚本的开头使用:
use open ':encoding(UTF-8)';
其他变体如here所述。这将为未明确指定图层的所有open
指令设置编码层。