charnames - 访问 Unicode 字符名称和命名字符序列;也定义字符名称
use charnames ':full';
print "\N{GREEK SMALL LETTER SIGMA} is called sigma.\n";
print "\N{LATIN CAPITAL LETTER E WITH VERTICAL LINE BELOW}",
" is an officially named sequence of two Unicode characters\n";
use charnames ':loose';
print "\N{Greek small-letter sigma}",
"can be used to ignore case, underscores, most blanks,"
"and when you aren't sure if the official name has hyphens\n";
use charnames ':short';
print "\N{greek:Sigma} is an upper-case sigma.\n";
use charnames qw(cyrillic greek);
print "\N{sigma} is Greek sigma, and \N{be} is Cyrillic b.\n";
use utf8;
use charnames ":full", ":alias" => {
e_ACUTE => "LATIN SMALL LETTER E WITH ACUTE",
mychar => 0xE8000, # Private use area
"自転車に乗る人" => "BICYCLIST"
};
print "\N{e_ACUTE} is a small letter e with an acute.\n";
print "\N{mychar} allows me to name private use characters.\n";
print "And I can create synonyms in other languages,",
" such as \N{自転車に乗る人} for "BICYCLIST (U+1F6B4)\n";
use charnames ();
print charnames::viacode(0x1234); # prints "ETHIOPIC SYLLABLE SEE"
printf "%04X", charnames::vianame("GOTHIC LETTER AHSA"); # prints
# "10330"
print charnames::vianame("LATIN CAPITAL LETTER A"); # prints 65 on
# ASCII platforms;
# 193 on EBCDIC
print charnames::string_vianame("LATIN CAPITAL LETTER A"); # prints "A"
use charnames
编译指令用于访问 Unicode 字符和命名字符序列的名称,并允许您定义自己的字符和字符序列名称。
所有形式的编译指令都允许使用以下 3 个函数
"charnames::string_vianame(name)" 用于运行时查找字符名称或命名字符序列,返回其字符串表示形式
"charnames::vianame(name)" 用于运行时查找字符名称(但不是命名字符序列)以获取其序号值(代码点)
"charnames::viacode(code)" 用于运行时查找代码点以获取其 Unicode 名称。
从 Perl v5.16 开始,双引号字符串中出现的任何 \N{CHARNAME}
序列都会自动加载此模块,参数为 :full
和 :short
(如下所述),前提是它尚未使用不同的参数加载,以便将命名的 Unicode 字符编译到字符串中的位置。在 v5.16 之前,需要显式使用 use charnames
来启用此用法。(但是,在 v5.16 之前,表单 "use charnames ();"
不会启用 \N{CHARNAME}
。)
请注意,\N{U+...}
(其中 ... 是一个十六进制数字)也会将字符插入字符串中。它插入的字符是其 Unicode 代码点(序数值)等于该数字的字符。例如,"\N{U+263a}"
是 Unicode(白色背景,黑色前景)笑脸,等效于 "\N{WHITE SMILING FACE}"
。另外请注意,当 ... 是一个数字(或用逗号分隔的数字对(参见 "perlreref 中的 QUANTIFIERS")时,\N{...}
可以表示正则表达式量词,而不是字符名称,并且与该 pragma 无关。
charnames
pragma 支持参数 :full
、:loose
、:short
、脚本名称和 自定义别名。
如果存在 :full
,则为了扩展 \N{CHARNAME}
,字符串 CHARNAME 首先会在标准 Unicode 字符名称列表中查找。
:loose
是 :full
的变体,它允许 CHARNAME 的指定不太精确。详细信息请参见 "LOOSE MATCHES"。
如果存在 :short
,并且 CHARNAME 的形式为 SCRIPT:CNAME
,则 CNAME 会在脚本 SCRIPT 中作为字母查找,如下一段所述。或者,如果 use charnames
与脚本名称参数一起使用,则对于 \N{CHARNAME}
,名称 CHARNAME 会在给定的脚本(按指定顺序)中作为字母查找。自定义别名可以覆盖这些,并在 "CUSTOM ALIASES" 中解释。
为了在给定的脚本 SCRIPTNAME 中查找 CHARNAME,该 pragma 会在标准 Unicode 名称表中查找以下名称:
SCRIPTNAME CAPITAL LETTER CHARNAME
SCRIPTNAME SMALL LETTER CHARNAME
SCRIPTNAME LETTER CHARNAME
如果 CHARNAME 全部为小写,则会忽略 CAPITAL
变体,否则会忽略 SMALL
变体,并且 CHARNAME 和 SCRIPTNAME 都将转换为全大写以进行查找。除此之外,如果还指定了 :loose
,则两者都遵循 松散 规则;否则严格遵循。
请注意,\N{...}
是编译时的;它是双引号字符串中使用的字符串常量的特殊形式;这意味着您不能在 \N{...}
中使用变量。如果您想要类似的运行时功能,请使用 charnames::string_vianame()。
注意,从 Perl 5.18 开始,BELL
指的是 Unicode 字符 U+1F514,而不是传统的 U+0007。对于后者,请使用 ALERT
或 BEL
。
如果 NAME
未知,则使用 \N{NAME}
会导致语法错误。
对于 \N{NAME}
,如果 use bytes
生效且输入名称是无法放入一个字节的字符的名称(即,其序数大于 255),则会发生致命错误。
否则,任何包含 \N{charname}
或 \N{U+code point}
的字符串将自动应用 Unicode 规则(参见 "perlunicode 中的字节和字符语义")。
通过指定 :loose
,将选择 Unicode 的 宽松字符名称匹配 规则,而不是其他情况下使用的严格精确匹配。这意味着 CHARNAME 不必那么精确地指定。大小写无关紧要(除了上面提到的脚本),也不需要任何下划线,只有名称中单词开头或结尾的连字符才重要(有一个例外:U+1180 HANGUL JUNGSEONG O-E
中的连字符很重要)。此外,与连字符不相邻的空格也不重要。官方 Unicode 名称在使用连字符还是空格来分隔类似单词的单元方面变化很大,此选项允许您不必太在意。非中间连字符重要的原因是像 U+0F60 TIBETAN LETTER -A
和 U+0F68 TIBETAN LETTER A
这样的情况。这里的连字符很重要,它前面的空格也很重要,因此两者都必须包含在内。
:loose
比 :full
慢 2 到 3 倍,但这种权衡可能对您来说是值得的。每次单独查找所需的时间非常短,并且结果会被缓存,因此速度差异只会出现在对许多不同拼写进行查找的程序中,而且可能只有在通过 vianame()
和 string_vianame()
进行查找时才会出现,因为 \N{...}
查找是在编译时完成的。
从 Unicode 6.1 和 Perl v5.16 开始,Unicode 定义了许多以前是 Perl 扩展的缩写和名称,以及一些 Perl 以前不接受的额外名称。这个列表太长了,这里无法全部列出,但您可以在 Unicode 网站上获取完整列表:http://www.unicode.org/Public/UNIDATA/NameAliases.txt.
早期版本的 Perl 接受了几乎所有 6.1 名称。这些名称在该 pod 的 v5.14 版本中得到了最广泛的记录:https://perldoc.perl5.cn/5.14.0/charnames.html#ALIASES.
您可以将自定义别名添加到标准 (:full
) Unicode 命名约定中。别名会覆盖任何标准定义,因此,如果您足够扭曲,您可以将 "\N{LATIN CAPITAL LETTER A}"
更改为 "B"
等。
别名必须以字母字符开头。之后,每个别名可以包含任何组合的单词 (\w
) 字符、空格 (U+0020)、连字符 (U+002D)、左括号 (U+0028) 和右括号 (U+0029)。最后两个字符不应该被允许出现在名称中,它们仅为了向后兼容而保留,并且可能会在 Perl 的未来版本中被弃用并删除,因此不要将它们用于新名称。(更准确地说,您指定的名称的第一个字符必须是与 \p{ID_Start}
、\p{Alphabetic}
和 \p{Gc=Letter}
全部匹配的字符。这确保了它是一个任何合理的人都会认为是字母字符的字符。并且,与 \w
匹配的延续字符也必须与 \p{ID_Continue}
匹配。) 从 Perl v5.18 开始,任何满足上述条件的 Unicode 字符都可以使用;在此之前,只有 Latin1 范围内的字符是可接受的。
别名可以映射到官方 Unicode 字符名称(而不是松散匹配的名称)或数字代码点(序数)。后者对于将名称分配给 Unicode 私有使用区域中的代码点很有用,例如 U+E800 到 U+F8FF。数字代码点必须是非负整数,或以 "U+"
或 "0x"
开头的字符串,其余部分被视为十六进制整数。文字数字常量必须是无符号的;如果它以零开头或包含非十进制十六进制数字,它将被解释为十六进制;否则它将被解释为十进制。如果它以 "U+"
开头,它将被解释为 Unicode 代码点;否则它将被解释为本地代码点。(只有低于 256 的代码点在 Unicode 和本地代码点之间可能不同。) 因此 U+41
始终是拉丁字母 "A";但 0x41
在 EBCDIC 平台上可能是 "NO-BREAK SPACE"。
别名可以通过匿名哈希添加
use charnames ":alias" => {
e_ACUTE => "LATIN SMALL LETTER E WITH ACUTE",
mychar1 => 0xE8000,
};
my $str = "\N{e_ACUTE}";
或者通过使用包含别名的文件添加
use charnames ":alias" => "pro";
这将尝试从 @INC
路径中读取 "unicore/pro_alias.pl"
。此文件应以纯 Perl 返回一个列表
(
A_GRAVE => "LATIN CAPITAL LETTER A WITH GRAVE",
A_CIRCUM => "LATIN CAPITAL LETTER A WITH CIRCUMFLEX",
A_DIAERES => "LATIN CAPITAL LETTER A WITH DIAERESIS",
A_TILDE => "LATIN CAPITAL LETTER A WITH TILDE",
A_BREVE => "LATIN CAPITAL LETTER A WITH BREVE",
A_RING => "LATIN CAPITAL LETTER A WITH RING ABOVE",
A_MACRON => "LATIN CAPITAL LETTER A WITH MACRON",
mychar2 => "U+E8001",
);
这两种方法都会自动将 ":full"
插入为第一个参数(如果没有其他参数给出),并且您也可以显式地给出 ":full"
,例如
use charnames ":full", ":alias" => "pro";
":loose"
对这些没有影响。输入名称必须完全匹配,使用 ":full"
规则。
此外,这两种方法目前只允许命名单个字符。要命名一系列字符,请使用 自定义翻译器(如下所述)。
这是 \N{...}
的运行时等效项。name 可以是任何表达式,该表达式计算结果为 \N{...}
在 :full
选项 下接受的名称 charnames
。此外,相同作用域中控制 "use charnames"
的任何其他选项都适用,例如 :loose
或任何 脚本列表,:short
选项,或您可能已定义的 自定义别名。
唯一的区别是 string_vianame
是运行时,而 \N{}
是编译时。您不能在 \N{}
中进行插值(因此 \N{$variable}
不起作用);如果输入名称未知,string_vianame
将返回 undef
,而不是语法错误。
这类似于 string_vianame
。主要区别在于,在大多数情况下,vianame
返回一个序数代码点,而 string_vianame
返回一个字符串。例如,
printf "U+%04X", charnames::vianame("FOUR TEARDROP-SPOKED ASTERISK");
打印 "U+2722"。
这导致了另外两个区别。由于返回单个代码点,因此该函数无法处理命名字符序列,因为这些序列由多个字符组成(对于这些序列,它返回 undef
。并且,代码点可以是任何字符的代码点,即使是那些在 use bytes
伪指令下不合法。
有关行为与上述描述不同的情况,请参阅 "BUGS"。
返回由数字代码指示的字符的完整名称。例如,
print charnames::viacode(0x2722);
打印“FOUR TEARDROP-SPOKED ASTERISK”。
返回的名称是代码点的“最佳”(定义如下)官方名称或别名(如果可用);否则是您为其定义的自定义别名(如果已定义);否则为 undef
。这意味着您的别名只会在没有官方 Unicode 名称(或别名)的代码点(例如专用代码点)上返回。
如果您为代码点定义了多个名称,则无法确定将返回哪个名称。
如上所述,如果代码点没有已知名称,则该函数将返回 undef
。在 Unicode 中,这些代码点的正确名称是空字符串,undef
字符串化为该字符串。(如果您请求的代码点超过了您未分配别名的合法 Unicode 最大值 U+10FFFF,您将获得 undef
以及警告。)
输入数字必须是非负整数,或者以 "U+"
或 "0x"
开头的字符串,其余部分被视为十六进制整数。文字数字常量必须是无符号的;如果它以零开头或包含非十进制十六进制数字,它将被解释为十六进制;否则它将被解释为十进制。如果它以 "U+"
开头,它将被解释为 Unicode 代码点;否则它将被解释为本机代码点。(只有低于 256 的代码点在 Unicode 和本机之间可能不同。)因此 U+41
始终是拉丁字母“A”;但 0x41
在 EBCDIC 平台上可能是“NO-BREAK SPACE”。
如上所述,在 "ALIASES" 中,Unicode 6.1 为某些代码点定义了额外的名称(同义词或别名),其中大多数已经作为 Perl 扩展可用。所有这些都被 \N{...}
和此模块中的其他函数接受,但 viacode
必须选择为给定输入代码点返回哪个名称,因此它返回“最佳”名称。要了解它是如何工作的,了解有关 Unicode 名称属性的更多信息将很有帮助。所有代码点实际上只有一个名称,该名称(从 Unicode 2.0 开始)在将字符分配给代码点后永远不会改变。但分配名称时确实出现过错误,例如,有时在发布标准时会发生文书错误,导致单词拼写错误,并且无法纠正这些错误。Name_Alias 属性最终被创建来处理这些情况。如果名称错误,将发布一个更正的同义词,使用 Name_Alias。viacode
将返回该更正的同义词作为代码点的“最佳”名称。(甚至有可能,尽管还没有发生,但更正本身需要更正,因此可以为该代码点创建另一个 Name_Alias;viacode
将返回最新的更正。)
每个控制字符(如换行符)的 Unicode 名称都是空字符串。但是,几乎所有字符都由其他标准(如 ASCII 标准)分配了名称,或者已在通用使用中。viacode
返回这些名称作为可用的“最佳”名称。Unicode 6.1 为每个控制字符创建了 Name_Aliases,包括备用名称,如换行符。viacode
使用原始名称“换行符”,而不是备用名称。类似地,返回的 U+FEFF 名称是“零宽度不间断空格”,而不是“字节顺序标记”。
在 Unicode 6.1 之前,4 个控制字符 U+0080、U+0081、U+0084 和 U+0099 没有名称或别名。为了保持向后兼容性,您为这些代码点定义的任何别名都将由此函数返回,优先于官方名称。
一些代码点也有缩写名称,例如“LF”或“NL”。viacode
永远不会返回这些名称。
由于名称更正可能会在未来的 Unicode 版本中添加,因此viacode
返回的名称可能会因此而改变。这是一个罕见的事件,但确实会发生。
\N{...}
转义的翻译机制是通用的,并且没有硬编码到 charnames.pm 中。模块可以在以下魔术咒语的范围内安装自定义翻译(在 use
模块的范围内):
sub import {
shift;
$^H{charnames} = \&translator;
}
这里 translator() 是一个子例程,它以 CHARNAME 作为参数,并返回要插入字符串中的文本,而不是 \N{CHARNAME}
转义。
这是创建自定义命名代码点序列的唯一方法。
由于要插入的文本在 bytes
模式下和不在 bytes
模式下应该不同,因此该函数应该检查 bytes
标志的当前状态,如:
use bytes (); # for $bytes::hint_bits
sub translator {
if ($^H & $bytes::hint_bits) {
return bytes_translator(@_);
}
else {
return utf8_translator(@_);
}
}
有关 CHARNAME 的限制,请参见上面的 "自定义别名"。
当然,vianame
、viacode
和 string_vianame
也需要被覆盖。
vianame() 通常返回一个序数代码点,但当输入名称为 U+...
格式时,它返回一个 chr。在这种情况下,如果 use bytes
生效并且字符无法放入一个字节中,它将返回 undef
并发出警告。
由于翻译函数的评估(参见 "自定义翻译器")发生在编译(字符串文字)的中间,因此翻译函数不应该执行任何 eval
或 require
。此限制应该在 Perl 的未来版本中解除(但优先级较低)。