一种编码覆盖了世界上大多数的书写系统。Web、大多数操作系统、Java和.NET的标准化编码。
在Unicode之前,每个脚本(或脚本族)都有自己的编码,或者更糟糕的是,许多不同的不兼容编码。Unicode几乎都是它们的超集,因此可以用于交换。
注意:到目前为止,代码示例都是以Perl为中心的,因为它有非常好的Unicodessupport支持,我知道这一点;如果您有其他语言的示例,请发表POSTA评论!
Unicode为每个字符定义一个代码点(数字),如a、ã、ې,不和☃。从Unicode6.2开始,共有109,976个代码点!(您可以将鼠标悬停在任何高亮显示的字符上以了解更多信息。)。
它还包括组合字符,例如可以添加到其他字符上的◌̀;这样,unicode就不需要为每个可能的字母和重音组合提供代码点。另一方面,Unicode通常不关心字体或样式差异:它给出和相同的代码点。
它不仅仅是一个字符集:它还包括标准编码,如UTF-8;小写/大写/标题大小写映射;排序规则(排序);换行符;呈现;从右到左的脚本处理,等等。
为了与其他编码兼容,Unicode有时包括预合成的字符版本,例如,这三个:
为了让它们在等价性测试等中被视为相同的字符串,您应该通过Unicode规范化来处理所有输入。最常见的形式是NFC,它在可能的情况下使用预先组成的字符,如果存在多个变音符号,则定义严格的变音符号顺序。NFD在可能的情况下分解字符。1个
只要保持一致,使用什么形式都无关紧要;NFD通常更快(代码点更少),tchrist建议通过NFD运行输入,通过NFC输出。
兼容性分解还将诸如ffi,Ⅸ甚至⁵之类的字符分别映射到“ffi”、“ix”和“5”。此NFKC规范化有助于搜索文本。
有些字符串在将case:?大写字母更改为‘ss’时实际上改变了长度。
在不区分大小写的比较中,ſ拉丁文小写字母Long S应被视为等于“s”和“S”。
Σ希腊文大写字母Sigma有两种小写形式:位于单词开头或中间的σ和位于单词末尾的ς。
不同地区的大小写基本一致,但土耳其语是个例外:它既有有点的i,也有无点的i,小写和大写都是如此。
为了确保您的代码能够处理这些情况以及任何新的情况,Unicode提供了单向“案例折叠”操作,允许不区分大小写的比较:
德语和瑞典语都有ä和ö,但排序不同-德语将它们视为相同字母的变体,没有变音(即‘aäbcdefghijklmnoöpqrstuvwxyz’),而瑞典人认为它们是新字母,并将它们放在末尾(‘abcdefghijklmnopqrstuvwxyzäö’)
排序也因应用程序而异;例如,电话簿的排序通常与图书索引不同。
对于汉字和其他表意文字,有许多可能的顺序,例如拼音(拼音)、按笔画计数等。
仅按二进制比较排序是不够的。而且代码点通常也没有任何合理的顺序。幸运的是,Unicode指定了一个非常可定制的排序算法,它覆盖了所有的边缘情况,并且做了一些聪明的事情来使它相当快。这里有一个例子:2。
#!/usr/bin/Perl Use Unicode::COLLATE::LOCAL;MY$COLLATOR=UNICODE::COLLATE::LOCAL->;new(LOCAL=&39;DE';DE';);my@sorted=$COLLATOR-&>;SORT(@ARRAY);$COLLATOR-&>CMP($WORD,$ANTHER_WORD);#-&>-1,0或1。
UCA还可以做其他聪明的事情,例如对‘2’后面的‘10’进行数字排序,或者对字符‘?’进行排序。就好像它是字符串“问号”一样。
较大的是UTF-8、UTF-16和UTF-32。每一个都保证了几乎每个码点3到字节序列的可逆映射。
UTF-32非常简单:每个码点都有4个字节。占用大量空间,不推荐用于互通。
UTF-8在网络上非常常见。它是面向字节的(没有字符顺序问题),可以很好地处理损坏,与ASCII兼容,并且占用最少的空间来存储主要是ASCII的文本(例如HTML)。
U+0800和U+FFFF之间的代码点(包括常用的CJKV字符)将占用3个字节,而不是2个字节。因此,UTF-16可能会更节省空间。
ASCII兼容性有助于允许UTF-8通过不支持Unicode的脚本和进程隐藏自己的方式。但是,如果这样的系统试图对数据(大小写、子字符串、正则表达式)执行任何操作,数据可能会损坏。
Java、.NET和Windows使用UTF-16。它使用2字节(16位)表示最常见的63K代码点,使用4字节表示不太常见的1M代码点(使用两个“代理”代码点)。
与人们普遍认为的相反,UTF-16不是固定宽度的编码。但只要它不包含代理,就可以将其视为代理,这可以加快字符串操作的速度。
UTF-16流通常以U+FEFF 4开始,以检测流的字符顺序(字节顺序)。否则,您可以通过‘UTF-16BE’或‘UTF-16LE’显式编码或解码,以指定字符顺序。
国际字符给域名带来了很大的问题。正如i和l看起来很相似一样,Unicode除了添加大量不可见的控制字符、空格字符和从右向左的文本外,还会将问题放大1000倍。
如果域包含来自多个脚本的字符和/或不属于用户首选语言之一的字符,则浏览器可能会以Punycode(见下文)显示该域。
RFC3491定义了nameprep,这是一种在字符串可以用于域名之前对字符串进行大小写折叠、规范化和消毒的机制。这将删除许多不可见的字符,如果使用了禁止的代码点,则会抛出错误。
它是通过称为Stringprep的更广泛的框架来实现的。在Perl中,可以使用Net::IDN::Encode,它还将执行Punycode转换。
由于传统原因,DNS不允许ASCII之外的扩展字符,因此Punycode是一种与ASCII兼容的编码方案。例如,café.com变成了xn--caf-dma.com。所有Punycode编码的域组件都可以通过它们的xn--前缀立即识别。
这也适用于TLD:。中国实际上被称为xn-fiqs8s。
至少在perl中,所有内容(子字符串、长度、索引、反向…)。在代码点级别上工作。这通常不是您想要的,因为用户认为像ў这样的字符实际上是两个代码点(y+◌̆)。这里有一篇关于这个主题的很不错的帖子。
即使像printf";%-10s";这样看似无害的东西,$str在组合字符、双角字符(例如中文/日文)或零角字符时也会完全中断。
幸运的是,Perl提供了\X正则表达式metachar,它与一个“扩展字素簇”(即用户认为的字符)完全匹配。更强大的解决方案是安装Unicode::GCString:
#!/usr/bin/perl使用Unicode::GCString;使用Unicode::Normalize;使用UTF8;使用OPEN QW(:std:Coding(UTF-8));my$s=NFD(";crème brúlée";);#确保组合标记获得自己的代码点my$g=Unicode::GCString->;new($s);打印$g->;长度,#';eélûRb EMÈrc';,not';éel̂urb em̀ecc';print$g-gt;substr(0,5),";\n";;#';crème';,not';crèm';print$g-gt;substr(0,3),";\n。123451234512345123451234512345|\n";;printf";%s%*s|\n";,$g,(25-$g->;列),';';;#25列长(ᵔᴥᵔ)printf";%-25s|\n";,$s;#22列长(╯°-°)╯︵┻━┻。
换行符(或换行)是一旦涉及Unicode就变得极其复杂的另一件事。您必须考虑各种不间断和间断控制字符、每种语言中的标点符号(例如,«和»引号,或在数字(如2,140)中使用的句号或逗号)以及每个字符的宽度。
自Perl5.6起,内置字符类(如\w、\b、\s和\d)支持Unicode(不过您需要确保您的字符串或模式启用了UTF8标志!)。使用/a标志禁用此功能(请参阅perlre)。
当您使用Unicode字符串作为文件名或目录名时,所有赌注都会失效。您使用的是什么编码?您使用的是什么接口?(Windows有两个,一个使用Unicode,另一个尝试使用与区域设置相关的编码)。一些文件系统执行标准化,比如对文件名执行NFD,比如MacOSX;如果您的平台不理解分解的Unicode,这可能是一个问题。
汉字是汉语、日语(汉字)以及历史上的朝鲜语和越南语的共同特征。许多字符具有不同的视觉外观,具体取决于脚本,但出于简单和性能原因(示例),Unicode将它们统一为单个代码点。
这引起了争议,因为一个字符的视觉形式可能是有意义的;用户可能不会看到他们的民族变体,而是其他国家的版本。直)。就像西方人的名字不同一样(例如。“John”或“Jon”)日语名字可能会使用Unicode不提供的特定字形变体,因此人们实际上不能按照自己喜欢的方式书写自己的名字!
在实践中,用户选择一种字体,以他们想要的样式呈现字形,可以是日文或中文。变体选择器(见下文)是该问题的另一个解决方案。
出于政治和传统原因(与旧字符集兼容),Unicode不会尝试统一简体中文和繁体中文。
Unicode 6.0版增加了722个“emoji”字符,这些表情符号主要在日本手机上使用,但最近在Mac OS X(Lion)、Gmail、iPhone和WindowsPhone 7中使用。一些字体可能会选择将它们呈现为全色表情符号;有些字体可能根本不支持它们。
表情符号是unicode包含🏩Love酒店和💩一堆便便的原因。(如果你看不到它们,安装Symbola,或者点击图片的fileformat.info链接)。
Unicode6.0的表情符号为许多国家的国旗引入了符号,但不是所有的。作为替代,范围U+1F1E6.。U+1F1FF定义从A到Z的符号。如果此范围内的两个符号形成ISO-3166-1国家代码(例如。‘FR’代表法国),则渲染器可以选择将其显示为旗帜!
变体选择器是在呈现字符之前更改字符呈现方式的代码点。有256个,它们占据了U+FE00的范围。U+FE0F和U+E0100.。U+E01EF+U+180B,U+180C和U+180D。
它们对于蒙古文是必不可少的,蒙古文有不同的字形形式,这取决于它在单词中的位置,单词的性别,附近有什么字母,单词是否是外来词,以及现代与传统正字法(细节)。
预计这些将被用来提供由汉统一统一的字形的变体。
它们还用于更深奥的事情,例如serif版本的数学运算符。
虽然叫‘零宽度不间断空格’,但用U+2060字拼接器更合适。--↩