内容

名称

perlunicook - Perl 中处理 Unicode 的食谱示例

描述

此手册页包含简短的食谱,演示如何在 Perl 中处理常见的 Unicode 操作,以及结尾处的一个完整程序。假设各个食谱中任何未声明的变量都已在其中具有先前的适当值。

示例

℞ 0:标准前导

除非另有说明,否则以下所有示例都需要此标准前导才能正常工作,其中 #! 已调整为在您的系统上工作

#!/usr/bin/env perl

use v5.36;     # or later to get "unicode_strings" feature,
               #   plus strict, warnings
use utf8;      # so literals and identifiers can be in UTF-8
use warnings  qw(FATAL utf8);    # fatalize encoding glitches
use open      qw(:std :encoding(UTF-8)); # undeclared streams in UTF-8
use charnames qw(:full :short);  # unneeded in v5.16

确实让 Unix 程序员也对二进制流使用 binmode,或使用 :raw 打开它们,但无论如何,这是获得它们的唯一便携方式。

警告use autodie(2.26 之前)和 use open 彼此不兼容。

℞ 1:通用 Unicode 智能过滤器

始终在输入时分解,然后在输出时重新组合。

use Unicode::Normalize;

while (<>) {
    $_ = NFD($_);   # decompose + reorder canonically
    ...
} continue {
    print NFC($_);  # recompose (where possible) + reorder canonically
}

℞ 2:微调 Unicode 警告

从 v5.14 开始,Perl 区分 UTF-8 警告的三个子类。

use v5.14;                  # subwarnings unavailable any earlier
no warnings "nonchar";      # the 66 forbidden non-characters
no warnings "surrogate";    # UTF-16/CESU-8 nonsense
no warnings "non_unicode";  # for codepoints over 0x10_FFFF

℞ 3:声明标识符和字面量的 utf8 源

如果没有至关重要的 use utf8 声明,在字面量和标识符中放置 UTF-8 将无法正常工作。如果您使用了上面给出的标准前导,则此操作已完成。如果您这样做了,则可以执行以下操作

use utf8;

my $measure   = "Ångström";
my @μsoft     = qw( cp852 cp1251 cp1252 );
my @ὑπέρμεγας = qw( ὑπέρ  μεγας );
my @鯉        = qw( koi8-f koi8-u koi8-r );
my $motto     = "👪 💗 🐪"; # FAMILY, GROWING HEART, DROMEDARY CAMEL

如果您忘记use utf8,高字节将被误认为是单独的字符,并且没有任何内容能够正常工作。

℞ 4:字符及其数字

ordchr函数对所有代码点透明地工作,而不仅仅是 ASCII,实际上,甚至不仅仅是 Unicode。

# ASCII characters
ord("A")
chr(65)

# characters from the Basic Multilingual Plane
ord("Σ")
chr(0x3A3)

# beyond the BMP
ord("𝑛")               # MATHEMATICAL ITALIC SMALL N
chr(0x1D45B)

# beyond Unicode! (up to MAXINT)
ord("\x{20_0000}")
chr(0x20_0000)

℞ 5:按字符数字表示的 Unicode 文字

在内插文字中,无论是双引号字符串还是正则表达式,您都可以使用\x{HHHHHH}转义字符通过其数字指定字符。

String: "\x{3a3}"
Regex:  /\x{3a3}/

String: "\x{1d45b}"
Regex:  /\x{1d45b}/

# even non-BMP ranges in regex work fine
/[\x{1D434}-\x{1D467}]/

℞ 6:按数字获取字符名称

use charnames ();
my $name = charnames::viacode(0x03A3);

℞ 7:按名称获取字符数字

use charnames ();
my $number = charnames::vianame("GREEK CAPITAL LETTER SIGMA");

℞ 8:Unicode 命名字符

使用\N{charname}表示法,通过该名称获取字符,以便在内插文字(双引号字符串和正则表达式)中使用。在 v5.16 中,有一个隐式的

use charnames qw(:full :short);

但在 v5.16 之前,您必须明确指定您想要哪一组字符名称。:full名称是官方 Unicode 字符名称、别名或序列,它们都共享一个名称空间。

use charnames qw(:full :short latin greek);

"\N{MATHEMATICAL ITALIC SMALL N}"      # :full
"\N{GREEK CAPITAL LETTER SIGMA}"       # :full

其他任何内容都是 Perl 特有的便捷缩写。如果您想要特定于脚本的短名称,请按名称指定一个或多个脚本。

"\N{Greek:Sigma}"                      # :short
"\N{ae}"                               #  latin
"\N{epsilon}"                          #  greek

v5.16 版本还支持:loose导入,用于对字符名称进行松散匹配,其工作方式与对属性名称进行松散匹配的方式相同:即,它忽略大小写、空格和下划线

"\N{euro sign}"                        # :loose (from v5.16)

从 v5.32 开始,您还可以使用

qr/\p{name=euro sign}/

在正则表达式中获取官方 Unicode 命名字符。始终对这些进行松散匹配。

℞ 9:Unicode 命名序列

这些看起来就像字符名称,但返回多个代码点。请注意printf中的%vx向量打印功能。

use charnames qw(:full);
my $seq = "\N{LATIN CAPITAL LETTER A WITH MACRON AND GRAVE}";
printf "U+%v04X\n", $seq;
U+0100.0300

℞ 10:自定义命名字符

使用:alias为现有字符提供您自己的词法作用域昵称,甚至为未命名的专用字符提供有用的名称。

use charnames ":full", ":alias" => {
    ecute => "LATIN SMALL LETTER E WITH ACUTE",
    "APPLE LOGO" => 0xF8FF, # private use character
};

"\N{ecute}"
"\N{APPLE LOGO}"

℞ 11:CJK 代码点的名称

像“東京”这样的汉字会返回CJK UNIFIED IDEOGRAPH-6771CJK UNIFIED IDEOGRAPH-4EAC的字符名称,因为它们的“名称”各不相同。CPAN Unicode::Unihan模块有一个大型数据库,用于对这些字符进行解码(以及更多内容),前提是您知道如何理解其输出。

# cpan -i Unicode::Unihan
use Unicode::Unihan;
my $str = "東京";
my $unhan = Unicode::Unihan->new;
for my $lang (qw(Mandarin Cantonese Korean JapaneseOn JapaneseKun)) {
    printf "CJK $str in %-12s is ", $lang;
    say $unhan->$lang($str);
}

打印

CJK 東京 in Mandarin     is DONG1JING1
CJK 東京 in Cantonese    is dung1ging1
CJK 東京 in Korean       is TONGKYENG
CJK 東京 in JapaneseOn   is TOUKYOU KEI KIN
CJK 東京 in JapaneseKun  is HIGASHI AZUMAMIYAKO

如果您心中有一个特定的罗马化方案,请使用特定模块

# cpan -i Lingua::JA::Romanize::Japanese
use Lingua::JA::Romanize::Japanese;
my $k2r = Lingua::JA::Romanize::Japanese->new;
my $str = "東京";
say "Japanese for $str is ", $k2r->chars($str);

打印

Japanese for 東京 is toukyou

℞ 12: 显式编码/解码

在罕见的情况下,例如数据库读取,您可能会收到需要解码的编码文本。

 use Encode qw(encode decode);

 my $chars = decode("shiftjis", $bytes, 1);
# OR
 my $bytes = encode("MIME-Header-ISO_2022_JP", $chars, 1);

对于所有编码都相同的流,不要使用编码/解码;相反,在打开文件时或在稍后使用 binmode(如下所述)设置文件编码。

℞ 13: 将程序参数解码为 utf8

    $ perl -CA ...
or
    $ export PERL_UNICODE=A
or
   use Encode qw(decode);
   @ARGV = map { decode('UTF-8', $_, 1) } @ARGV;

℞ 14: 将程序参数解码为区域设置编码

# cpan -i Encode::Locale
use Encode qw(locale);
use Encode::Locale;

# use "locale" as an arg to encode/decode
@ARGV = map { decode(locale => $_, 1) } @ARGV;

℞ 15: 声明 STD{IN,OUT,ERR} 为 utf8

使用命令行选项、环境变量,或显式调用 binmode

    $ perl -CS ...
or
    $ export PERL_UNICODE=S
or
    use open qw(:std :encoding(UTF-8));
or
    binmode(STDIN,  ":encoding(UTF-8)");
    binmode(STDOUT, ":utf8");
    binmode(STDERR, ":utf8");

℞ 16: 声明 STD{IN,OUT,ERR} 为区域设置编码

# cpan -i Encode::Locale
use Encode;
use Encode::Locale;

# or as a stream for binmode or open
binmode STDIN,  ":encoding(console_in)"  if -t STDIN;
binmode STDOUT, ":encoding(console_out)" if -t STDOUT;
binmode STDERR, ":encoding(console_out)" if -t STDERR;

℞ 17: 使文件 I/O 默认为 utf8

在没有编码参数的情况下打开的文件将采用 UTF-8

    $ perl -CD ...
or
    $ export PERL_UNICODE=D
or
    use open qw(:encoding(UTF-8));

℞ 18: 使所有 I/O 和参数默认为 utf8

    $ perl -CSDA ...
or
    $ export PERL_UNICODE=SDA
or
    use open qw(:std :encoding(UTF-8));
    use Encode qw(decode);
    @ARGV = map { decode('UTF-8', $_, 1) } @ARGV;

℞ 19: 使用特定编码打开文件

指定流编码。这是处理编码文本的正常方式,而不是调用低级函数。

# input file
    open(my $in_file, "< :encoding(UTF-16)", "wintext");
OR
    open(my $in_file, "<", "wintext");
    binmode($in_file, ":encoding(UTF-16)");
THEN
    my $line = <$in_file>;

# output file
    open($out_file, "> :encoding(cp1252)", "wintext");
OR
    open(my $out_file, ">", "wintext");
    binmode($out_file, ":encoding(cp1252)");
THEN
    print $out_file "some text\n";

除了编码之外,还可以指定更多的层。例如,咒语 ":raw :encoding(UTF-16LE) :crlf" 包括隐式 CRLF 处理。

℞ 20: Unicode 大小写

Unicode 大小写与 ASCII 大小写有很大不同。

uc("henry ⅷ")  # "HENRY Ⅷ"
uc("tschüß")   # "TSCHÜSS"  notice ß => SS

# both are true:
"tschüß"  =~ /TSCHÜSS/i   # notice ß => SS
"Σίσυφος" =~ /ΣΊΣΥΦΟΣ/i   # notice Σ,σ,ς sameness

℞ 21: Unicode 不区分大小写的比较

在 CPAN Unicode::CaseFold 模块中也可用,v5.16 中新的 fc “foldcase” 函数授予与 /i 模式修饰符始终使用的相同的 Unicode 折叠大小写功能

use feature "fc"; # fc() function is from v5.16

# sort case-insensitively
my @sorted = sort { fc($a) cmp fc($b) } @list;

# both are true:
fc("tschüß")  eq fc("TSCHÜSS")
fc("Σίσυφος") eq fc("ΣΊΣΥΦΟΣ")

℞ 22: 匹配正则表达式中的 Unicode 换行序列

Unicode 换行符匹配双字符 CRLF 分形图素或任何七个垂直空白字符。适用于处理来自不同操作系统的文本文件。

\R

s/\R/\n/g;  # normalize all linebreaks to \n

℞ 23: 获取字符类别

查找数字代码点的通用类别。

use Unicode::UCD qw(charinfo);
my $cat = charinfo(0x3A3)->{category};  # "Lu"

℞ 24: 禁用内置 charclasses 中的 Unicode 识别

禁用 \w\b\s\d 以及 POSIX 类在 Unicode 上正常工作,无论是在此范围内还是仅在一个正则表达式中。

use v5.14;
use re "/a";

# OR

my($num) = $str =~ /(\d+)/a;

或者使用特定的非 Unicode 属性,如 \p{ahex}\p{POSIX_Digit}。无论使用哪种字符集修饰符(/d /u /l /a /aa),属性仍正常工作。

℞ 25: 在正则表达式中使用 \p、\P 匹配 Unicode 属性

这些都匹配具有给定属性的单个代码点。使用 \P 代替 \p 来匹配缺少该属性的代码点。

\pL, \pN, \pS, \pP, \pM, \pZ, \pC
\p{Sk}, \p{Ps}, \p{Lt}
\p{alpha}, \p{upper}, \p{lower}
\p{Latin}, \p{Greek}
\p{script_extensions=Latin}, \p{scx=Greek}
\p{East_Asian_Width=Wide}, \p{EA=W}
\p{Line_Break=Hyphen}, \p{LB=HY}
\p{Numeric_Value=4}, \p{NV=4}

℞ 26: 自定义字符属性

在编译时定义你自己的自定义字符属性以用于正则表达式。

# using private-use characters
sub In_Tengwar { "E000\tE07F\n" }

if (/\p{In_Tengwar}/) { ... }

# blending existing properties
sub Is_GraecoRoman_Title {<<'END_OF_SET'}
+utf8::IsLatin
+utf8::IsGreek
&utf8::IsTitle
END_OF_SET

if (/\p{Is_GraecoRoman_Title}/ { ... }

℞ 27: Unicode 规范化

通常在输入时呈现为 NFD,在输出时呈现为 NFC。使用 NFKC 或 NFKD 函数可提高搜索召回率,假设你已经对要搜索的文本执行了相同的操作。请注意,这不仅仅是预先组合的兼容性字形;它还根据规范组合类重新排列标记,并清除单例。

use Unicode::Normalize;
my $nfd  = NFD($orig);
my $nfc  = NFC($orig);
my $nfkd = NFKD($orig);
my $nfkc = NFKC($orig);

℞ 28: 转换非 ASCII Unicode 数字

除非你使用了 /a/aa,否则 \d 匹配的不仅仅是 ASCII 数字,但 Perl 的隐式字符串到数字转换当前无法识别这些数字。以下是如何手动转换此类字符串。

use v5.14;  # needed for num() function
use Unicode::UCD qw(num);
my $str = "got Ⅻ and ४५६७ and ⅞ and here";
my @nums = ();
while ($str =~ /(\d+|\N)/g) {  # not just ASCII!
   push @nums, num($1);
}
say "@nums";   #     12      4567      0.875

use charnames qw(:full);
my $nv = num("\N{RUMI DIGIT ONE}\N{RUMI DIGIT TWO}");

℞ 29: 匹配正则表达式中的 Unicode 音节

程序员可见的“字符”是 /./s 匹配的代码点,但用户可见的“字符”是 /\X/ 匹配的音节。

# Find vowel *plus* any combining diacritics,underlining,etc.
my $nfd = NFD($orig);
$nfd =~ / (?=[aeiou]) \X /xi

℞ 30: 按音节而不是按代码点提取(正则表达式)

# match and grab five first graphemes
my($first_five) = $str =~ /^ ( \X{5} ) /x;

℞ 31: 按音节而不是按代码点提取(子字符串)

# cpan -i Unicode::GCString
use Unicode::GCString;
my $gcs = Unicode::GCString->new($str);
my $first_five = $gcs->substr(0, 5);

℞ 32: 按音节反转字符串

按代码点反转会搞乱变音符号,错误地将 crème brûlée 转换为 éel̂urb em̀erc 而不是 eélûrb emèrc;因此,按音节反转。无论字符串处于何种规范化状态,这两种方法都可以正常工作

$str = join("", reverse $str =~ /\X/g);

# OR: cpan -i Unicode::GCString
use Unicode::GCString;
$str = reverse Unicode::GCString->new($str);

℞ 33: 音节中的字符串长度

字符串 brûlée 有六个音节,但最多有八个代码点。这是按音节计数,而不是按代码点计数

my $str = "brûlée";
my $count = 0;
while ($str =~ /\X/g) { $count++ }

 # OR: cpan -i Unicode::GCString
use Unicode::GCString;
my $gcs = Unicode::GCString->new($str);
my $count = $gcs->length;

℞ 34: Unicode 打印列宽

Perl 的 printfsprintfformat 认为所有代码点都占用 1 个打印列,但许多代码点占用 0 或 2 个。这里为了表明规范化没有区别,我们打印出两种形式

use Unicode::GCString;
use Unicode::Normalize;

my @words = qw/crème brûlée/;
@words = map { NFC($_), NFD($_) } @words;

for my $str (@words) {
    my $gcs = Unicode::GCString->new($str);
    my $cols = $gcs->columns;
    my $pad = " " x (10 - $cols);
    say str, $pad, " |";
}

生成此内容以表明无论规范化如何,它都能正确填充

crème      |
crème      |
brûlée     |
brûlée     |

℞ 35: Unicode 排序

按数字代码点排序的文本不遵循合理的字母顺序;使用 UCA 对文本进行排序。

use Unicode::Collate;
my $col = Unicode::Collate->new();
my @list = $col->sort(@old_list);

请参阅 Unicode::Tussle CPAN 模块中的 ucsort 程序,以获取此模块的便捷命令行界面。

℞ 36: 不区分大小写重音的 Unicode 排序

指定强度为 1 级,以忽略大小写和变音符号,仅查看基本字符。

use Unicode::Collate;
my $col = Unicode::Collate->new(level => 1);
my @list = $col->sort(@old_list);

℞ 37: Unicode 语言环境排序

一些语言环境有特殊的排序规则。

# either use v5.12, OR: cpan -i Unicode::Collate::Locale
use Unicode::Collate::Locale;
my $col = Unicode::Collate::Locale->new(locale => "de__phonebook");
my @list = $col->sort(@old_list);

上面提到的 ucsort 程序接受一个 --locale 参数。

℞ 38: 使用 cmp 对文本进行操作,而不是代码点

代替此方法

@srecs = sort {
    $b->{AGE}   <=>  $a->{AGE}
                ||
    $a->{NAME}  cmp  $b->{NAME}
} @recs;

使用此方法

my $coll = Unicode::Collate->new();
for my $rec (@recs) {
    $rec->{NAME_key} = $coll->getSortKey( $rec->{NAME} );
}
@srecs = sort {
    $b->{AGE}       <=>  $a->{AGE}
                    ||
    $a->{NAME_key}  cmp  $b->{NAME_key}
} @recs;

℞ 39: 大小写 重音不敏感的比较

使用排序器对象按字符而不是代码点比较 Unicode 文本。

use Unicode::Collate;
my $es = Unicode::Collate->new(
    level => 1,
    normalization => undef
);

 # now both are true:
$es->eq("García",  "GARCIA" );
$es->eq("Márquez", "MARQUEZ");

℞ 40: 大小写 重音不敏感的区域设置比较

相同,但在特定区域设置中。

my $de = Unicode::Collate::Locale->new(
           locale => "de__phonebook",
         );

# now this is true:
$de->eq("tschüß", "TSCHUESS");  # notice ü => UE, ß => SS

℞ 41: Unicode 换行

根据 Unicode 规则将文本分成多行。

# cpan -i Unicode::LineBreak
use Unicode::LineBreak;
use charnames qw(:full);

my $para = "This is a super\N{HYPHEN}long string. " x 20;
my $fmt = Unicode::LineBreak->new;
print $fmt->break($para), "\n";

℞ 42: Unicode 文本在 DBM 哈希中,繁琐的方法

如果任何代码点不适合一个字节,则使用常规 Perl 字符串作为 DBM 哈希的键或值将触发宽字符异常。以下是手动管理转换的方法

   use DB_File;
   use Encode qw(encode decode);
   tie %dbhash, "DB_File", "pathname";

# STORE

   # assume $uni_key and $uni_value are abstract Unicode strings
   my $enc_key   = encode("UTF-8", $uni_key, 1);
   my $enc_value = encode("UTF-8", $uni_value, 1);
   $dbhash{$enc_key} = $enc_value;

# FETCH

   # assume $uni_key holds a normal Perl string (abstract Unicode)
   my $enc_key   = encode("UTF-8", $uni_key, 1);
   my $enc_value = $dbhash{$enc_key};
   my $uni_value = decode("UTF-8", $enc_value, 1);

℞ 43: Unicode 文本在 DBM 哈希中,简单的方法

以下是隐式管理转换的方法;所有编码和解码都是自动完成的,就像附加了特定编码的流一样

   use DB_File;
   use DBM_Filter;

   my $dbobj = tie %dbhash, "DB_File", "pathname";
   $dbobj->Filter_Value("utf8");  # this is the magic bit

# STORE

   # assume $uni_key and $uni_value are abstract Unicode strings
   $dbhash{$uni_key} = $uni_value;

 # FETCH

   # $uni_key holds a normal Perl string (abstract Unicode)
   my $uni_value = $dbhash{$uni_key};

℞ 44: PROGRAM: Unicode 排序和打印演示

这是一个完整的程序,展示了如何利用区分区域设置的排序、Unicode 大小写以及管理打印宽度(当某些字符占用零或两列,而每次不只占用一列时)。运行后,以下程序将生成此对齐良好的输出

Crème Brûlée....... €2.00
Éclair............. €1.60
Fideuà............. €4.20
Hamburger.......... €6.00
Jamón Serrano...... €4.45
Linguiça........... €7.00
Pâté............... €4.15
Pears.............. €2.00
Pêches............. €2.25
Smørbrød........... €5.75
Spätzle............ €5.50
Xoriço............. €3.00
Γύρος.............. €6.50
막걸리............. €4.00
おもち............. €2.65
お好み焼き......... €8.00
シュークリーム..... €1.85
寿司............... €9.99
包子............... €7.50

以下是该程序。

#!/usr/bin/env perl
# umenu - demo sorting and printing of Unicode food
#
# (obligatory and increasingly long preamble)
#
use v5.36;
use utf8;
use warnings  qw(FATAL utf8);    # fatalize encoding faults
use open      qw(:std :encoding(UTF-8)); # undeclared streams in UTF-8
use charnames qw(:full :short);  # unneeded in v5.16

# std modules
use Unicode::Normalize;          # std perl distro as of v5.8
use List::Util qw(max);          # std perl distro as of v5.10
use Unicode::Collate::Locale;    # std perl distro as of v5.14

# cpan modules
use Unicode::GCString;           # from CPAN

my %price = (
    "γύρος"             => 6.50, # gyros
    "pears"             => 2.00, # like um, pears
    "linguiça"          => 7.00, # spicy sausage, Portuguese
    "xoriço"            => 3.00, # chorizo sausage, Catalan
    "hamburger"         => 6.00, # burgermeister meisterburger
    "éclair"            => 1.60, # dessert, French
    "smørbrød"          => 5.75, # sandwiches, Norwegian
    "spätzle"           => 5.50, # Bayerisch noodles, little sparrows
    "包子"              => 7.50, # bao1 zi5, steamed pork buns, Mandarin
    "jamón serrano"     => 4.45, # country ham, Spanish
    "pêches"            => 2.25, # peaches, French
    "シュークリーム"    => 1.85, # cream-filled pastry like eclair
    "막걸리"            => 4.00, # makgeolli, Korean rice wine
    "寿司"              => 9.99, # sushi, Japanese
    "おもち"            => 2.65, # omochi, rice cakes, Japanese
    "crème brûlée"      => 2.00, # crema catalana
    "fideuà"            => 4.20, # more noodles, Valencian
                                 # (Catalan=fideuada)
    "pâté"              => 4.15, # gooseliver paste, French
    "お好み焼き"        => 8.00, # okonomiyaki, Japanese
);

my $width = 5 + max map { colwidth($_) } keys %price;

# So the Asian stuff comes out in an order that someone
# who reads those scripts won't freak out over; the
# CJK stuff will be in JIS X 0208 order that way.
my $coll  = Unicode::Collate::Locale->new(locale => "ja");

for my $item ($coll->sort(keys %price)) {
    print pad(entitle($item), $width, ".");
    printf " €%.2f\n", $price{$item};
}

sub pad ($str, $width, $padchar) {
    return $str . ($padchar x ($width - colwidth($str)));
}

sub colwidth ($str) {
    return Unicode::GCString->new($str)->columns;
}

sub entitle ($str) {
    $str =~ s{ (?=\pL)(\S)     (\S*) }
             { ucfirst($1) . lc($2)  }xge;
    return $str;
}

另请参阅

请参阅以下手册页,其中一些是 CPAN 模块:perlunicodeperlunipropsperlreperlrecharclassperluniintroperlunitutperlunifaqPerlIODB_FileDBM_FilterDBM_Filter::utf8EncodeEncode::LocaleUnicode::UCDUnicode::NormalizeUnicode::GCStringUnicode::LineBreakUnicode::CollateUnicode::Collate::LocaleUnicode::UnihanUnicode::CaseFoldUnicode::TussleLingua::JA::Romanize::JapaneseLingua::ZH::Romanize::PinyinLingua::KO::Romanize::Hangul

Unicode::Tussle CPAN 模块包含许多程序来帮助处理 Unicode,包括以下程序,用于全部或部分替换标准实用程序:使用 tcgrep 替换 egrep,使用 uniquote 替换 cat -vhexdump,使用 uniwc 替换 wc,使用 unilook 替换 look,使用 unifmt 替换 fmt,使用 ucsort 替换 sort。要了解 Unicode 字符名称和字符属性,请参阅其 unipropsunicharsuninames 程序。它还提供以下程序,它们都是执行 Unicode 操作的通用过滤器:unititleunicapsuniwideuninarrowunisupersunisubsnfdnfcnfkdnfkc;以及 uclctc

最后,请参阅已发布的 Unicode 标准(页码来自版本 6.0.0),包括以下特定附件和技术报告

§3.13 默认大小写算法,第 113 页;§4.2 大小写,第 120-122 页;大小写映射,第 166-172 页,特别是第 170 页开始的无大小写匹配。
UAX #44:Unicode 字符数据库
UTS #18:Unicode 正则表达式
UAX #15:Unicode 规范化形式
UTS #10:Unicode 排序算法
UAX #29:Unicode 文本分段
UAX #14:Unicode 换行算法
UAX #11:东亚宽度

作者

Tom Christiansen <[email protected]> 撰写了本文档,偶尔会得到 Larry Wall 和 Jeffrey Friedl 的建议。

版权和许可

版权所有 © 2012 Tom Christiansen。

本程序是免费软件;您可以在与 Perl 相同的条款下重新分发或修改它。

这些示例大部分取自“骆驼书”的当前版本;也就是说,取自《Perl 编程》的第 4 版,版权所有 © 2012 Tom Christiansen <et al.>,2012-02-13 由 O’Reilly Media 出版。代码本身可以自由重新分发,并且我们鼓励您移植、折叠、纺锤和修改本手册中的任何示例,以便将其包含到您自己的程序中,而没有任何负担。通过代码注释进行确认是礼貌的,但不是必需的。

修订历史

v1.0.0 – 首次公开发布,2012-02-27