我想知道为什么大多数使用Perl构建的现代解决方案在默认情况下不启用UTF-8。
我知道核心Perl脚本存在许多遗留问题,在这些问题上它可能会破坏某些东西。但是,从我的观点来看,在21世纪,大的新项目(或者有大的视角的项目)应该让他们的软件UTF-8从头开始证明。但我还是看不到。例如,驼鹿启用严格和警告,但不启用Unicode。Modern::Perl也减少了样板文件,但没有UTF-8处理。
为什么?在2011年的现代Perl项目中,是否有一些理由避免使用UTF-8?
评论@tchrist的时间太长,所以我在这里添加了它。
我好像没说清楚。让我试着增加一些东西。
我和克赖斯特的看法很相似,但我们的结论完全相反。我同意,使用Unicode的情况很复杂,但这就是为什么我们(Perl用户和编码人员)需要一些层(或pragma),这使得UTF-8处理变得像现在一样简单。
TChrist指出了很多要涵盖的方面,我会读几天甚至几周来思考它们。不过,这不是我的观点。tchrist试图证明"启用utf-8"没有一种单一的方法。我没有那么多的知识来反驳这一点。所以,我坚持活生生的例子。
我和拉库多一起玩过,UTF-8就在我需要的时候。我没有任何问题,只是起作用了。也许在更深的地方有一些限制,但是在开始的时候,我测试的所有东西都像我预期的那样工作。
这难道不是现代Perl 5的目标吗?我更强调:我并不是建议将utf-8作为核心Perl的默认字符集,而是建议为开发新项目的人员使用快照来触发它。
另一个例子,但语气更为消极。框架应该使开发更容易。几年前,我尝试过Web框架,但因为"启用UTF-8"太模糊,所以把它们扔掉了。我找不到如何和在何处挂接Unicode支持。这太费时了,我发现走老路比较容易。现在我看到这里有一个赏金来处理与Mason2相同的问题:如何使Mason2utf-8干净?因此,这是一个非常新的框架,但是将它与UTF-8结合使用需要对其内部结构有深入的了解。就像一个红色的大标志:停下来,别用我!
我真的很喜欢Perl。但是处理unicode是很痛苦的。我仍然发现自己在靠墙跑。某种程度上,tchrist是对的,它回答了我的问题:新项目不吸引utf-8,因为它在Perl 5中过于复杂。
- 大家好-在这些评论中有一些标志。我所做的是在这里截取评论的快照,并将它们放到这个聊天室中,您可以在这里进行讨论:chat.stackoverflow.com/rooms/846/…
- 很抱歉,但我同意@tchrist——utf-8非常难。没有一个框架或工具只是"翻转一个开关",然后正确地处理它。这是在设计应用程序时必须直接考虑的问题,而不是任何框架或语言都能为您处理的问题。如果rakudo恰好为您工作,那么您对测试案例的冒险性就不够了——因为它将以@tchrist's answer和butcher中的几个例子为例。
- 你到底希望驼鹿或现代人:Perl会做什么?神奇地将文件和数据库中随机编码的字符数据再次转换为有效数据?
- @比利·奥尼尔:循环浏览@tchrist列表,没有人而且只有治愈方法。我同意。还有一些通用级别的UTF-8处理,它是可插拔的,正是如此,这有助于开发人员进入游戏。我认为,在这个新模块中,utf8::all的知识是非常好的开始。如果它(或类似的功能)在核心中,并且perluniintro建议它作为快速启动,那就更好了。
- @Jrockway:Modern::Perl的目的是什么?减少样板文件并介绍当前Perl中可用技术的最佳实践。包括这里的UTF-8处理套装很好,imho。与moose类似:它是Perl的现代对象系统。那么,为什么不在moose中进行另一个步骤并将utf-8作为默认字符集呢?
- 那是什么意思?驼鹿与文本操作无关。为什么它应该知道字符编码,更不用说为您选择默认编码了?(无论如何,您列出的杂注不接触编码的原因是Perl杂注影响词汇行为。假设包括其他模块在内的整个世界都是UTF-8,那么做完全是错误的。这里不是php或ruby。)
- (还有……)大多数现代Perl应用程序"在UTF-8上中断?"我当然从来没有写过一个应用程序,无论是Perl还是其他应用程序,它都不是Unicode清除的。)
- 铌。tchrist(tom christansen)发布了关于unicode的[training.perl.com/oscon2011/index.html tom christansen's materials for oscon2011]。题为"Unicode支持爆炸:好的,坏的,和(大部分)丑陋的"的一篇文章谈到了不同编程语言中的Unicode支持。只有google go和perl5支持完整的unicode,只有google go内置(没有提到perl6)。
- 您的问题是关于任何一个操作系统吗?最有投票权的答案似乎是针对Linux的。或者至少特定于除MacOS X以外的Unices。
- @Hippietrail:我主要在Linux上工作,但我也看到过很多与Win相关的与UTF-8相关的Perl问题。我对MacOSX的了解太少,但据我所知,同样的问题也应该在Mac中出现。如果没有,我很高兴它,并期待着很快与Perl在Mac上合作。
- 如果我使用的是POSIX系统,并且将ENV['LC_ALL']设置为"en-u-us.utf-8",那么这是一个明确的意图声明,Perl应该通过假设其标准输入编码为utf-8,并对其标准输出进行同样的编码来实现这一点。如果我的代码因为不处理Unicode的许多细微之处而中断,也许我不应该在声称是Unicode的环境中运行它。我不明白为什么Perl应该忽略区域设置,而不管它的默认值是什么。
- 我对它的研究不多,但utf8::似乎都能满足我的基本需求。FWW,我认为在Java中使用UTF-8的一种(公开)简单性是Perl可以从中受益匪浅。
??????????????????????????&???????????&????????&?????&??????????????????????????????????????????????????????????????????????????是吗??????????????????????????&????????????????????????????????????????????
把你的PERL_UNICODE设为可嫉妒的AS。这使得所有Perl脚本都将@ARGV解码为utf?8个字符串,并将所有三个stdin、stdout和stderr的编码都设置为utf?8。这两者都是整体效应,而不是词汇效应。好的。
在源文件(程序、模块、库、doHickey)的顶部,突出地声明您正在运行Perl 5.12版或更高版本,方法是:好的。
use v5.12; # minimal for unicode string feature好的。
use v5.14; # optimal for unicode string feature好的。
启用警告,因为以前的声明只启用严格和功能,而不启用警告。我还建议将Unicode警告提升为异常,因此使用这两行,而不仅仅是其中一行。但是,请注意,在v5.14下,utf8警告类包含三个可单独启用的子警告:nonchar、surrogate和non_unicode。这些你可能希望对其施加更大的控制。好的。
use warnings;好的。
use warnings qw( FATAL utf8 );好的。
声明此源单元编码为utf?8。尽管从前这个语用法做了其他的事情,但现在它只为这一个单独的目的服务,而不是为其他目的服务:好的。
use utf8;好的。
声明在这个词汇范围内打开文件句柄但在其他地方不打开文件句柄的任何操作都假定流是以UTF编码的?8除非你另有说明。这样就不会影响其他模块或其他程序的代码。好的。
use open qw( :encoding(UTF-8) :std );好的。
通过
{CHARNAME}启用命名字符。好的。
use charnames qw( :full :short );好的。
如果您有一个DATA句柄,则必须显式设置其编码。如果你想用UTF?8,然后说:好的。
binmode(DATA,":encoding(UTF-8)");好的。
当然,您最终可能会发现自己所关心的其他问题没有尽头,但是这些问题足以近似于状态目标,即"使所有事情都只与UTF一起工作"。8",尽管对这些术语的理解有所减弱。好的。
另一个pragma虽然与Unicode无关,但它是:好的。
强烈推荐。好的。&是吗??是否?????&??????????????&?????????????????是否??
说"Perl应该(不知何故)!]默认情况下,启用Unicode"甚至不会开始考虑在某些罕见和孤立的情况下说足够多的话,甚至是稍微有用的话。unicode不仅仅是一个更大的字符库;它也是这些字符以多种方式交互的方式。好的。
即使是一些人认为他们想要的最简单的措施,也会不幸地打破数以百万计的代码行,这些代码没有机会"升级"到你新的勇敢的新世界现代性。好的。
这比人们假装的要复杂得多。在过去的几年里,我一直在思考这个问题。我很想被证明我错了。但我不认为我是。Unicode从根本上来说比您想要强加给它的模型要复杂得多,而且这里的复杂性是您永远无法在地毯下扫描的。如果你尝试,你会破坏你自己的代码或者其他人的代码。在某个时候,你只需要破坏并学习Unicode是关于什么的。你不能假装它不是什么东西。好的。
??努力使unicode变得简单,比我以前用过的任何东西都要简单得多。如果你认为这不好,试试别的。然后回来??:要么你会回到一个更好的世界,要么你会带来同样的知识,这样我们就可以利用你的新知识来创造??更好地处理这些事情。好的。&是吗?????????????????????????????????????????????????????????????????????????????????????????????????????????
至少,这里有一些看起来需要的东西??要"默认启用Unicode",如您所说:好的。
全部??默认情况下,源代码应为UTF-8。你可以用use utf8或export PERL5OPTS=-Mutf8来获得。好的。
这个??DATA手柄应为UTF-8。您必须按每个包进行此操作,如binmode(DATA,":encoding(UTF-8)")中所述。好的。
程序参数到??默认情况下,脚本应理解为UTF-8。export PERL_UNICODE=A或perl -CA或export PERL5OPTS=-CA。好的。
标准输入、输出和错误流应默认为UTF-8。全部为export PERL_UNICODE=S,或部分为I、O、和/或E。这就像perl -CS。好的。
是否有其他手柄被打开??除非另有声明,否则应视为UTF-8;对于其中特定的一种,应视为export PERL_UNICODE=D或I和O;export PERL5OPTS=-CD起作用。这就使得所有人都得到了以东的支持。好的。
覆盖两个基地加上你用export PERL5OPTS=-Mopen=:utf8,:std打开的所有溪流。见唯一。好的。
您不想错过UTF-8编码错误。试试export PERL5OPTS=-Mwarnings=FATAL,utf8。确保您的输入流始终是binmoded到:encoding(UTF-8),而不仅仅是:utf8。好的。
128–255之间的代码点应该理解为??作为相应的Unicode码位,而不仅仅是未经处理的二进制值。use feature"unicode_strings"或export PERL5OPTS=-Mfeature=unicode_strings。这将使uc("\xDF") eq"SS"和"\xE9" =~ /\w/。一个简单的export PERL5OPTS=-Mv5.12或更好的版本也能得到。好的。
指定的Unicode字符在默认情况下不启用,因此添加export PERL5OPTS=-Mcharnames=:full,:short,latin,greek或某些类似字符。请参见取消命名和tcgrep。好的。
您几乎总是需要从标准的Unicode::Normalize模块访问各种类型的分解的函数。export PERL5OPTS=-MUnicode::Normalize=NFD,NFKD,NFC,NFKD,然后总是通过nfd运行传入的内容,从nfc运行传出的内容。我还没有知道这些的I/O层,但请参阅NFC、NFD、NFKD和NFKC。好的。
字符串比较??使用eq、ne、lc、cmp、sort、&c&cc总是错误的。所以你需要的不是@a = sort @b,而是@a = Unicode::Collate->new->sort(@b)。不妨把它加到你的export PERL5OPTS=-MUnicode::Collate上。您可以缓存用于二进制比较的键。好的。
??像printf和write这样的内置模块对unicode数据做了错误的处理。前者需要使用Unicode::GCString模块,后者也需要使用Unicode::LineBreak模块。见UWC和Unifmt。好的。
如果你想让它们算作整数,那么你就必须通过Unicode::UCD::num函数运行\d+捕获,因为?内置的ATOI(3)目前还不够聪明。好的。
您要处理文件系统问题吗?文件系统。一些文件系统静默地强制转换为NFC;另一些则静默地强制转换为NFD。而其他人仍然在做其他事情。有些人甚至完全忽视了这件事,这会导致更大的问题。所以你必须做你自己的NFC/NFD处理来保持健康。好的。
你所有的??涉及a-z或a-z的代码必须更改,包括m//、s///和tr///。你的代码被破坏了,这应该是一个引人注目的危险信号。但目前尚不清楚该如何改变。获得正确的属性,并了解它们的casefolds,比您想象的要困难。我每天都用独角兽和独角兽。好的。
使用\p{Lu}的代码几乎和使用[A-Za-z]的代码一样错误。你需要用\p{Upper}来代替,并知道原因。是的,\p{Lowercase}和\p{Lower}与\p{Ll}和\p{Lowercase_Letter}不同。好的。
使用[A-Za-z]的代码更糟。不能使用\pL或\p{Letter},需要使用\p{Alphabetic}。不是所有的字母都是字母,你知道的!好的。
如果你在找??使用/[\$\@\%]\w+/的变量,则出现问题。您需要查找/[\$\@\%]\p{IDS}\p{IDC}*/,即使这样也不会考虑标点符号变量或包变量。好的。
如果要检查空白,则应根据情况在\h和\v之间进行选择。你不应该使用\s,因为它并不意味着[\h\v],这与大众的看法相反。好的。
如果您使用
作为线边界,或者甚至使用
,那么您做的是错误的。你必须使用
,这是不一样的!好的。
如果您不知道何时以及是否调用Unicode::StringPrep,那么最好学习一下。好的。
不区分大小写的比较需要检查两个事物是否是相同的字母,不管它们的发音是否相同。最简单的方法是使用标准的unicode::collate模块。Unicode::Collate->new(level => 1)->cmp($a, $b)。还有eq方法等等,你可能也应该学习match和substr方法。这些都有明显的优势?内置的。好的。
有时这还不够,而您需要使用unicode::collate::locale模块,就像在Unicode::Collate::Locale->new(locale =>"de__phonebook", level => 1)->cmp($a, $b)中那样。假设Unicode::Collate::->new(level => 1)->eq("d","e")是正确的,但Unicode::Collate::Locale->new(locale=>"is",level => 1)->eq("d"," e")是错误的。同样,"ae"和"?"如果你不使用本地语言,或者如果你使用英语的话,他们在冰岛的本地语言中是不同的。现在怎么办?我告诉你,这很难。您可以使用ucsort来测试其中的一些内容。好的。
考虑如何匹配字符串"ni"中的模式cvcv(辅音、元音、辅音、元音)?O"。它的NFD形式——你最好记住把它放进去——变成了"ninx 303 o"。现在你打算怎么做?即使假装一个元音是[aeiou](顺便说一下,这是错误的),你也不能做类似(?=[aeiou])\X)的事情,因为即使在nfd中,一个像'?'不分解!不过,使用我刚刚向您展示的UCA比较,它将测试等于"o"。你不能依赖NFD,你必须依赖UCA。好的。
&是吗??是否?????????????????&?????????????????????????????是否??
但这并不是全部。人们对Unicode有无数种错误的假设。直到他们理解这些事情,他们的??代码将被破坏。好的。
假定它可以打开文本文件而不指定编码的代码被破坏。好的。
假定默认编码是某种本机平台编码的代码被破坏。好的。
假设日文或中文网页占用较少的UTF空间的代码?16比UTF?8是错的。好的。
假定Perl使用UTF的代码?8内部错误。好的。
假定编码错误总是引发异常的代码是错误的。好的。
假定Perl代码点被限制为0x10_ffff的代码是错误的。好的。
假定您可以将$/设置为可以使用任何有效行分隔符的代码是错误的。好的。
在案例折叠上假定往返相等的代码,如lc(uc($s)) eq $s或uc(lc($s)) eq $s,是完全错误的。假设uc("σ")和uc("?")都是"Σ",但lc("Σ")不可能同时返回这两个值。好的。
假定每个小写代码点都有一个独特的大写代码点,或者反之亦然的代码被破坏。例如,"a"是没有大写的小写字母;而"?"和"?"都是字母,但不是小写字母;但是,它们都是没有相应大写版本的小写代码点。明白了吗?他们不是\p{Lowercase_Letter},尽管他们是\p{Letter}和\p{Lowercase}。好的。
假定更改大小写而不更改字符串长度的代码已中断。好的。
假定只有两种情况的代码被破坏。还有乳脂酶。好的。
假定只有字母有大小写的代码被破坏。除了字母之外,数字、符号甚至符号都有表壳。事实上,改变情况甚至可以使一些东西改变其主要的一般类别,例如,一个\p{Mark}变成一个\p{Letter}。它还可以使它从一个脚本切换到另一个脚本。好的。
假定案例从不依赖区域设置的代码将被破坏。好的。
假定Unicode给出了有关POSIX区域设置被破坏的图的代码。好的。
假定您可以删除音调符号以获取基本的ASCII字母的代码是邪恶的,仍然的,破碎的,大脑受损的,错误的,以及死刑的理由。好的。
假定发音符号\p{Diacritic}和标记\p{Mark}相同的代码被破坏。好的。
假设\p{GC=Dash_Punctuation}覆盖的代码与\p{Dash}被破坏的代码相同。好的。
假定破折号、连字符和减号是相同的代码,或者假定每个代码只有一个破折号和减号的代码是错误的。好的。
假定每个代码点占用不超过一个打印列的代码被破坏。好的。
假定所有\p{Mark}字符占用零打印列的代码都已中断。好的。
假定相似字符相同的代码被破坏。好的。
假定不相似的字符不相似的代码将被破坏。好的。
假定一行中只有一个\X可以匹配的代码点数量有限制的代码是错误的。好的。
假定\X不能以\p{Mark}字符开头的代码是错误的。好的。
假定\X不能包含两个非\p{Mark}字符的代码是错误的。好的。
假定它不能使用"\x{FFFF}"的代码是错误的。好的。
假定非BMP代码点需要两个UTF-16(代理)代码单元的代码将编码为两个单独的UTF-8字符(每个代码单元一个)是错误的。它不是:它编码到单个代码点。好的。
如果在生成的utf-8的开头放置了一个BOM,那么从utf-16或utf-32转码到utf-8的代码就会被破坏。这太蠢了,工程师应该把眼皮去掉。好的。
假设CESU-8是一个有效的UTF编码错误。Likewise,code that thinks concoding U+0000 as "\xC0\x80"is UTF-8 is broken and wrong.这些人也需要眼睛治疗。
okay.
假设特征如>〔1〕〔1〕〔1〕〔1〕〔2〕〔1〕的时刻点〕左边的时刻点是错误的,因为事实上它们不正确。
okay.
假设你第一次输出X和第二次Y的字符,这些字符将以XY的字符出现,那是错误的。有时候他们不会
okay.
假设美国信息交换标准码对英文写作来说足够好的代码是愚蠢的,短视的,非法的,破碎的,邪恶的,错误的。离开他们的头!如果看上去太极端,我们可以妥协:亨瑟福斯,他们可能只是一只脚上的大脚趾(剩下的仍然是鸭子)。
okay.
假设所有的\p{Math}点代码都是错误的。
okay.
只有信件、文摘和理解是错误的。
okay.
假设^和~是错误的标记。
okay.
假设埃多克斯1〔10〕是错误的。
okay.
他们中任何信都是错误的。
okay.
相信\p{InLatin}的法典和\p{Latin}的法典是一样的。
okay.
相信\p{InLatin}的代码,是最常用的,肯定是错的。
okay.
《守则》相信给$FIRST_LETTER的第一封信是在一些字母表和$LAST_LETTER中写成的,最后一封信是在同一个字母表中写成的,该字母表是[${FIRST_LETTER}-${LAST_LETTER}]的。
okay.
代码相信某人的名字只能包含某些性格是愚蠢的,进攻性的,错误的。
okay.
ASCII试图减少Unicode的代码并不是错误的,其永久代码不应再被允许在编程中工作。周期我甚至不认为他们应该再次见到他们,因为他们显然没有这么好。
okay.
代码相信有某种方式可以假装文本文件编码不存在是破碎和危险的。也许把另一只眼睛也挖出来了。
okay.
Code that converts unknown characters to ?is broken,stupid,braindead,and runs contrary to the standard recommendation,which says not to do that!RTFM for why not.
okay.
代码相信它可以可靠地估计一个未标记的文本文件的编码是一个致命混合物的胡布里斯和纳米比亚的标记。因为宙斯只会发出一个闪电
okay.
你相信可以使用的代码?给PAD和Justify Unicode数据的Widths是破碎和错误的。
okay.
如果代码认为一旦您成功地使用给定的名称创建了一个文件,那么当您在其封闭目录上运行ls或readdir时,您实际上会发现使用您创建的文件名创建的文件有问题、损坏和错误。别惊讶了!好的。
认为UTF-16是固定宽度编码的代码是愚蠢的、破坏的和错误的。吊销他们的编程许可证。好的。
处理一个平面上的代码点的代码与处理其他平面上的代码点不同,这实际上是错误的。回到学校去。好的。
认为像/s/i这样的东西只能与"S"或"S"匹配的代码是错误的和错误的。你会很惊讶的。好的。
使用\PM\pM*来查找图形集群而不是使用\X的代码是错误的,并且是错误的。好的。
希望回到ASCII世界的人们应该被全心全意地鼓励这样做,为了纪念他们光荣的升级,他们应该免费提供一台预电动手动打字机来满足他们所有的数据输入需要。发送给他们的消息应该通过????????S电报,每行40个字符,由快递员亲手递送。停下来。好的。
&是吗???????????????????????????????????????????????????????????????????????????????????????????????????????
最近我自己的样板看起来像这样:好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| use 5.014;
use utf8 ;
use strict ;
use autodie ;
use warnings ;
use warnings qw < FATAL utf8 >;
use open qw < :std :utf8 >;
use charnames qw < :full >;
use feature qw < unicode_strings >;
use File ::Basename qw < basename >;
use Carp qw < carp croak confess cluck >;
use Encode qw < encode decode >;
use Unicode ::Normalize qw < NFD NFC >;
END { close STDOUT }
if (grep /\P{ASCII}/ => @ARGV) {
@ARGV = map { decode ("UTF-8", $_) } @ARGV;
}
$0 = basename ($0); # shorter messages
$| = 1;
binmode(DATA ,":utf8");
# give a full stack dump on any untrapped exceptions
local $SIG{__DIE__} = sub {
confess "Uncaught exception: @_" unless $^S;
};
# now promote run-time warnings into stackdumped exceptions
# *unless* we're in an try block, in which
# case just generate a clucking stackdump instead
local $SIG{__WARN__} = sub {
if ($^S) { cluck "Trapped warning: @_" }
else { confess "Deadly warning: @_" }
};
while (<>) {
chomp;
$_ = NFD ($_);
...
} continue {
say NFC ($_);
}
__END__ |
&是吗????????????????????????
我不知道还有多少"默认Unicode"在?"你能得到比我写的还要多的东西。是的,我知道:你也应该使用Unicode::Collate和Unicode::LineBreak。可能更多。好的。
正如您所看到的,有太多的unicode东西您真的需要担心,以便永远存在"默认为unicode"之类的东西。好的。
你会发现什么,就像我们以前一样??5.8,不可能把所有这些东西强加给从一开始就没有设计好的代码来解释它们。你善意的自私刚刚打破了整个世界。好的。
即使你这样做了,仍然有一些关键问题需要大量的思考才能解决。没有可以翻转的开关。只有大脑,我的意思是真正的大脑,在这里就足够了。你必须学习很多东西。模退到手动打字机前,你简直不能指望在无知中偷偷摸摸。这是21??世纪,你不可能希望Unicode因故意的无知而消失。好的。
你必须学会。时期。"一切都能正常工作"永远不会这么容易,因为这将保证很多事情都不能正常工作,这就使得人们认为"一切都能正常工作"的假设失效。好的。
你可能会得到一些合理的违约,为极少数和非常有限的操作,但不需要考虑的事情比我认为你有很多。好的。
作为一个例子,规范化排序将导致一些真正的头痛。???"\x{F5}"?'"o\x{303}"'?'"o\x{303}\x{304}"'?和"o\x{304}\x{303}"_?'是否应全部匹配'?但你到底要怎么做呢?这比看起来难,但这是你需要解释的。???好的。
如果我对Perl有一点了解的话,那就是它的unicode位的作用和不作用,我向您保证:"???????????????????S??????????U???????????????????????????????????????????????????????"?"?好的。
你不能仅仅改变一些默认值,顺利航行。我跑步是真的吗??将PERL_UNICODE设置为"SA",但仅此而已,即使这主要用于命令行。对于真正的工作,我要完成上面列出的所有步骤,我非常非常仔细地完成它。好的。?????DL??????????怎么办?聚氨基甲酸酯???P????U??????????NL POO????好啊。
- 就像谢尔姆彭德利指出的:"所有的!"如果我今天写些新的东西,UTF-8应该是完成工作的最简单方法。不是这样。你的样板很好用。并不是每个人都有这样的知识来把这么多的摔倒者转到正确的位置。很抱歉,我度过了漫长而艰难的一天,所以我将在明天的主条目中用示例进行更多的评论。
- @WK:所以像perl -i.bak -pe 's/foo/bar'这样的代码中断很酷?世界上有很多这样的事情。您希望对eq进行哪种比较?UCA3比较?lc是否将其转化为UCA1?你怎么知道?如何匹配部分和/或不连续的字形?所有包含8位数据的旧代码现在都无法编译,这可以吗?Perl不再处理二进制数据可以吗?可以得到不同的答案吗?未经他们同意,就从地下人那里骗过a-z可以吗?分解笔迹可以吗?是否可以接受100倍的排序代码减速?文件系统呢?
- @tchrist:当我们在新项目中启用Unicode时,为什么要破坏一些旧代码?让我们忘记遗留代码和核心Perl。例如,在基于moose的项目中是否有任何理由避免使用utf-8?如果没有,我认为moose可以尽可能广泛地支持utf-8,因为它支持警告和严格的pragma。现在我们只是在浪费时间,因为已经有很多用驼鹿写的代码,可能会被破坏;)
- 从上面的列表中可以明显看出一个结论:不要插科打诨。别这样,永远不要。计算成本高,语义依赖于"locale"尝试识别失败的内容。
- 我是唯一一个感到讽刺的人吗?在FF/Chrome/IE/Opera上,Tchrist的这篇文章呈现出如此大的不同,有时甚至难以辨认?
- @WK:最明显的问题是utf8出血,数据从支持Unicode的上下文传输到不支持Unicode的上下文(即:在代码、数据库、主机环境(OS、文件系统等)中使用的第三方代码),这些环境可能存在危险。如果您没有对数据库接口使用准备好的/绑定好的查询,那么我有一个坏消息要告诉您。
- 尽管很好奇,您是否打算让许多Unicode字符由于缺乏字体支持而无法读取。
- @肯特:如果他们没有使用预先准备好的查询,他们可能也会有一些其他的惊喜,SQL注入是目前孩子们最喜欢的脚本攻击方法之一。而且,他们的代码会很慢…
- 虽然我通常喜欢这篇文章,而且投出了赞成票,但有一件事让我很恼火。有很多"代码…被打破了。虽然我不反对这一说法,但我认为最好表现出自己的破碎。以这种方式,它将从咆哮到教育(答案的这一部分)。
- 虽然我不完全同意这个答案的一些含义(我觉得确实有一些与Unicode相关的Perl文化问题),但这是讨论的问题:这是一个很好的答案,这就是为什么它如此有价值。我特别同意"假定断断续续"的总座右铭(不是Onyl代表Perl)
- @不,我没有故意使用有问题的代码点;这是一个让你安装乔治·杜罗斯的超级棒符号字体的阴谋,它涵盖了Unicode 6.0。???@Depesz这里没有空间解释为什么每个断开的连接都是错误的。@Leonbloy很多这样的代码都适用于Unicode,而不仅仅是Perl。有些材料可能会出现在??编程Perl??,第4版,10月出版。???我还有一个月的时间?处理它,而unicode是?????那里;也有正则表达式
- @谢天谢地,这有助于我们看到一个大局。不过,我相信,要解决你指出的所有问题,至少需要10年时间。为了有效地解决这些问题,我们需要每天使用Unicode。如果我们说"unicode问题太复杂了,让我们先解决它们,然后制定一个理想的解决方案,然后使用",我们就不能前进了。而且大多数成长中的软件直到今天,即使在最低水平上,也不会采用UTF-8。必须要有明确的依据(如utf8::all,但我更喜欢核心部分)。你可以称之为"兽医"。
- 即使安装了symbola字体,msie 9也不会呈现骆驼和其他符号。同一台Windows7 PC上的火狐3.6可以重新命名所有字符。
- 我安装了symbola,它不能用chrome修复。不知道我是否需要重新启动?Unicode很难实现。
- @斯马克夫:在铬合金下,symbola使它对我很好,这和歌剧差不多。Safari有正确的标志符号,但似乎对某些文本块有非缩放的想法。不知道为什么你的铬不好,但我的呢?
- @Leonbloy:你说"我觉得Perl文化与Unicode之间确实存在一些问题",我是?????????????????????????有兴趣在这里多听听你的观点。我正好同意你的意见,但我不想"带领证人"把话放在你嘴里。如果这里没有足够的空间进入,请毫不犹豫地把这件事发到我的标准地址????????????????????????????????????????????& 65308;??????????????????????????????????????????和65310;????????????????????????????????????????????????????????????????????????????????????????
- 样板文件中的"use strict"是多余的,如果您说过"use 5.14.0",那么默认情况下它是打开的。
- @马克:不,这不是多余的。我不知道谁会决定他们不想一直走到5点14分。如果他们退到足够远的地方,严格的规定就消失了,我永远不希望发生这种情况。因此它不是多余的。另外,它是声明性的,因此很有用。同样,我喜欢将unicode_strings功能明确化,这样人们就会意识到它的有效性。这就像我经常将事情初始化为0的方式,即使我不需要这样做:我喜欢发出我的意图的信号。我不喜欢秘密的副作用。
- 有趣的是,在安装了符号字体(ubuntu/chromium)之后,一些符号出现了,另一些仍然是框,如果我加亮并单击鼠标右键,chromium会在Google中搜索该字符,该字符在上下文菜单中显示得很好!
- 完美答案。但问题的要点仍然在这里。在21世纪,应该使用Unicode,更简单,更直观。是的,比"这里没有魔法子弹"还要明白。但是框架开发人员(如上面的mason2)确实应该关心它。是的,我比志愿者工作了解得多,当我不喜欢这个框架时,很容易不使用它。但是Perl中所有Unicode的疯狂行为确实伤害了Perl本身。
- @JM666我同意您这么多:我们应该在所有新代码中采用零容忍策略vis-&224;-vis Unicode兼容性。是的,您必须区分字节的二进制文件和其中包含字符的文本文件,但是严重滥用的p?S????S?B????自古以来就不得不这样做。就我而言,任何处理文本的新代码都必须假定并理解Unicode。我在上面给出了如何通过环境来有选择地升级一些现有程序的建议。但每个人都需要知道Unicode。这与Perl有关。
- @你是对的,我理解并同意你的回答。1。(如你所说)模块开发人员。我喜欢志愿者开发人员——但在21世纪,对于不支持Unicode的CPAN提交,应该是零容忍。只需删除或(至少标记它们)。非Unicode就绪模块会伤害Perl!2。Perl6-我希望Perl6将启用默认的utf8(因为不需要保持向后兼容)。-老实说,我对Perl6还一无所知。类似uni::perl(我正在使用它)(或者类似于您的烤肉盘)的东西应该是核心的,以便于启用所有通用的utf8特性。
- onlamp.com/pub/a/oreilly/perl/usage??
- @YSH:考虑到我个人有Tim的特别许可,可以使用??在为我的网站、文章和业务讨论Perl时,考虑到我是第四版编程Perl的主要作者,但我仍然没有完成其草稿,我发现Tim很可能不会生气。我当然不希望。如果我很难做到的话,我相信我可以把这篇文章转载给他做广告。
- @奇里斯特:那是个笑话。但是第四版S/referent/thingy/可以吗?我更喜欢它。
- @我不知道。在2E的时候,我们对thingie很感兴趣。所以在第三季,乔恩和我,也许还有达米安,说服拉里去参加全民公决。但我承认我有时会再次求助于思考。但这似乎是一种奇怪的混合体,一方面有不请自来的感觉,另一方面又有思想障碍,是吗?Larry有权在4E上进行最后一次编辑,所以当他读到那些章节(我已经完成了)时,我们会看到他做了什么。
- 刚发现比样板不完全工作,因为在"自动挖掘"的错误。当使用open qw(:utf8:std)pragma时,"use autodie"会稍微关闭它。所以要么打开,要么自动驾驶-不是两个都打开…;)(旧Perl错误:stackoverflow.com/questions/4959384/&hellip;)
- @JM666:是的,没错。我忘记提了。我也找到了。这很烦人。从技术上讲,它应该是use open qw<:encoding(UTF-8) :std>,因为您应该使用严格的utf8版本,而不是松散的版本。
- 是的,:)但是即使如此,也很难将样板文件转换为包中的"使用my::correcutfPerl"。(如stackoverflow.com/q/6412799/632407中所示)
- "假定&252;有umlaut的代码是错误的。"—为什么?我搜索并找到了2篇关于这个主题的文章:en.wikipedia.org/wiki/%c3%9c->en.wikipedia.org/wiki/diaeresis(发音符号)。引自第二篇文章:"这两种用途是分开起源的,分封的时间要长得多。在使用Unicode的现代计算机系统中,umlaut和diaeresis音调符号是相同的:?和228?表示a-umlaut和a-diaeresis。"Perl是真的吗?
- @Nordicdyno:在NFC中没有COMBINING DIAERESIS。此外,也有类似于NKO COMBINING DOUBLE DOT ABOVE的东西。但是,是的,这个标记的名字是"分封"。这两种功能在本质上是不同的:例如,在西班牙语单词arg&252;elles中,没有发生umlaut,在法语na&239;ve中也有类似的情况。关键是你不能通过事物的外表来判断它。
- @我怎样才能知道我看你的帖子是否完全正确?我已经安装了symbola字体,它大大改进了一些东西,但是仍然有一些白色方块——应该有吗?我需要一个单元测试!!!!
- "认为某人的名字只能包含某些字符的代码是愚蠢的、冒犯的和错误的。"Unicode是否采用了以前称为Prince的艺术家的新名字?
- "Unicode太复杂,无法保证安全";)
- 令人惊讶的好答案,即使对我们这些在Perl中没有花太多时间的人来说也是非常有用的:)顺便说一句,23号。(取决于区域设置的排序规则),您已经得到"&240";其中它应该是"&240";(使其非常不相等=P)
- @tchrist"试图将unicode转换成ascii的代码不仅是错误的,而且不应该再让它的实施者在编程中工作了。"所以你解雇了堆栈交换团队?
- @但是说真的,+1代表假设部分。这些需要更广泛的了解。
- ????????????????后的?是什么意思?
- @J.F.塞巴斯蒂安,这是处方的服用标准。它是RX符号。
- training.perl.com目前已关闭,但unifmt等实用程序可以在cpan上找到,例如search.cpan.org/perldoc?统一IFMT
- 这是一个惊人的伟大答案!但我必须指出一个重要的问题。Perl可以在许多平台上运行,但这个答案似乎只处理主流的Unix风格的操作系统。例如,所有的export FOO=BAR都不能在Windows上工作,一些关于"alien"文件系统的内容将是错误的,因为Windows使用UTF-16和Mac OS X,尽管它使用UTF-8强制一种特定的规范化形式,这种形式不会随着新的Unicode版本的出现而改变。在这些操作系统上运行它们将是本地文件系统,而Unix文件系统将是外来文件系统。
- "只要您成功地用给定的名称创建了一个文件,那么当您在其封闭目录上运行ls或readdir时,您实际上会发现用您创建的名称创建的文件有缺陷、损坏和错误。"—我说,任何对其用户这样做的文件系统API都是问题的根源,而不是用户的代码—应该是固定的。为什么这种行为被认为是正确的?用您的话说,这种文件系统API的作者应该是…好吧,你自己选择任何可怕的惩罚,你似乎很擅长。
- (1)在理论上,你所说的很多都是正确的,但在实践中——好吧,很少有人有足够的天赋同时处理你所做的每一项规定,并且能够完成任何有用的工作;当然,数量还不足以为那些需要Perl程序员的公司中的很大一部分提供服务。(2)即使启用默认情况下包含的样板文件是疯狂的,也没有理由将来的Perl版本不能使用相应的use $versionpragma按需启用它。更疯狂的是,仅仅在Perl中启用Unicode就需要大约50行代码。
- 最后一点是,这里的许多规定意味着,任何给定语言的个人(包括母语者)对自己的语言都将有绝对正确的理解;在一般情况下,这是不真实的,对于特定的个人来说,这是很少真实的,因此可以完全作为一种可能性予以驳回;它还假定总是需要"正确"的行为!程序的存在是为了服务于人们,而不是为了完美——正确性仅仅是一致地执行所需行为的副作用——即使所需行为是"不正确的"!
- 我认为从Perl5.16开始,您可以使用内置的fc()而不是unicode::casefold。
- binmode(DATA,":utf8");与use utf8;是冗余的,因为DATA只是Perl解析器用来读取文件的文件句柄。
- @你说得对。只有在编译单元中没有use utf8;时才需要它。因为很多时候你不知道,它是单独列出的,因为use open不会抓住它。
- 您忘记提到53号:假定字符具有可信任的属性的代码被破坏。Unicode标准的每一个版本都有一些缺陷。你引用了一个完美的例子:大写字母"A"是小写字母。在任何情况下,这都不可能是正确的,所以您可以打赌这将在将来发生变化,从而破坏您今天编写的所有代码。我知道所有关于Unicode对未来校对的"保证",它们几乎和Unicode一样坏。
- 现在是2015年,我有一个全补丁的操作系统/浏览器(Windows7上的火狐),部分答案仍然不能正确呈现。我该怎么做才能看到这个答案(或者所有坏的控制字符都是问题的一部分?)
- @亚历克斯在Mac电脑上总是很好看。
处理Unicode文本有两个阶段。第一个问题是"我如何在不丢失信息的情况下输入和输出它"。第二个问题是"如何根据当地语言惯例处理文本"。好的。
奇里斯特的文章涵盖了这两个方面,但第二部分是他文章中99%的文本来自哪里。大多数程序甚至不能正确处理I/O,所以在开始担心规范化和排序之前,了解这一点很重要。好的。
这篇文章旨在解决第一个问题好的。
当您将数据读取到Perl中时,它不关心它是什么编码。它分配一些内存并将字节存储在那里。如果你说print $str,它只会将这些字节直接发送到你的终端,而终端可能会设置为假定所有写入它的内容都是utf-8,你的文本就会出现。好的。
不可思议的。好的。
但事实并非如此。如果您试图将数据视为文本,您将看到发生了一些错误。您只需进一步观察length,就可以看到Perl对字符串的看法和您对字符串的看法不一致。写一行像:perl -E 'while(<>){ chomp; say length }',输入文字化け,你得到12…回答不正确,4.好的。
这是因为Perl假定您的字符串不是文本。你必须先告诉它是文本,然后它才能给你正确的答案。好的。
这很简单;编码模块有这样的功能。通用入口点是Encode::decode(当然也可以是use Encode qw(decode))。这个函数从外部世界获取一些字符串(我们称之为"八位字节",这是一种奇特的说法"8位字节"),并将其转换为Perl可以理解的文本。第一个参数是字符编码名称,如"utf-8"或"ascii"或"euc-jp"。第二个参数是字符串。返回值是包含文本的Perl标量。好的。
(也有Encode::decode_utf8,它假定编码为utf-8。)好的。
如果我们重写一行代码:好的。
1
| perl -MEncode=decode -E 'while(<>){ chomp; say length decode("UTF-8", $_) }' |
我们输入文字并得到"4"。成功。好的。
这就是Perl中99%的Unicode问题的解决方案。好的。
关键是,每当程序中出现任何文本时,必须对其进行解码。因特网不能传输字符。文件不能存储字符。数据库中没有字符。只有八位字节,在Perl中不能将八位字节视为字符。必须使用编码模块将编码的八位字节解码为Perl字符。好的。
另一半的问题是从程序中获取数据。这很容易,只需说use Encode qw(encode),就可以确定数据的编码方式(utf-8到能够理解utf-8、utf-16在Windows上的文件等的终端),然后输出encode($encoding, $data)的结果,而不只是输出$data的结果。好的。
此操作将Perl的字符(即程序所操作的字符)转换为外部世界可以使用的八位字节。如果我们可以通过互联网或终端发送字符,那就容易多了,但我们不能:只发送八位字节。所以我们必须将字符转换成八位字节,否则结果是未定义的。好的。
总结:对所有输出进行编码并对所有输入进行解码。好的。
现在,我们将讨论三个问题,这些问题使这项工作有点具有挑战性。第一个是图书馆。他们处理文本是否正确?答案是…他们尝试。如果你下载了一个网页,lwp会把你的结果作为文本返回给你。如果对结果调用正确的方法,也就是说(恰好是decoded_content,而不是content,它只是从服务器中得到的八位字节流。)数据库驱动程序可能会不稳定;如果只使用perl就使用dbd::sqlite,它会成功,但如果其他工具在数据B中放入了以utf-8以外的编码形式存储的文本。ASE…好。。。只有编写代码来正确地处理它,才能正确地处理它。好的。
输出数据通常比较容易,但是如果你看到"打印中的宽字符",那么你就知道你在某处把编码弄乱了。这个警告意味着"嘿,你想把Perl字符泄露给外界,但这没有任何意义"。您的程序似乎可以工作(因为另一端通常正确处理原始Perl字符),但它非常中断,随时可能停止工作。用一个明确的Encode::encode来修复它!好的。
第二个问题是UTF-8编码的源代码。除非在每个文件的顶部说use utf8,否则Perl不会假定源代码是utf-8。这意味着,每次你说像my $var = 'ほげ'这样的话,你都会将垃圾注入你的程序,这会彻底破坏所有的东西。您不必"使用utf8",但如果不使用,则程序中不能使用任何非ASCII字符。好的。
第三个问题是Perl如何处理过去。很久以前,还没有Unicode这样的东西,Perl认为一切都是拉丁语1文本或二进制。因此,当数据进入程序并开始将其视为文本时,Perl将每个八位字节视为拉丁-1字符。这就是为什么,当我们要求"文字化"的长度时,我们得到了12。Perl假设我们在操作拉丁-1字符串"?????"(12个字符,有些是非打印字符)。好的。
这被称为"隐式升级",这是一件非常合理的事情,但如果你的文本不是拉丁语-1,这不是你想要的。这就是为什么显式解码输入很关键:如果不这样做,Perl会这样做,而且它可能会出错。好的。型
人们会遇到这样的问题:一半的数据是一个合适的字符串,有些数据仍然是二进制的。Perl将解释仍然是二进制的部分,就像它是拉丁-1文本一样,然后将其与正确的字符数据结合起来。这会使你看起来像是正确地处理你的角色,破坏了你的程序,但实际上,你只是没有足够的修复它。好的。型
这里有一个例子:你有一个程序读取一个UTF-8编码的文本文件,你在每一行上附加一个Unicode PILE OF POO,然后打印出来。你写得像:好的。型
1 2 3 4
| while(<>){
chomp;
say "$_ ??";
} |
然后运行一些UTF-8编码的数据,比如:好的。型
1
| perl poo.pl input-data.txt |
号
它用每行末尾的poo打印utf-8数据。太好了,我的程序工作了!好的。型
但不,你只是在做二进制连接。您正在从文件中读取八位字节,用chomp删除一个
,然后在PILE OF POO字符的utf-8表示中附加字节。当您修改程序来解码文件中的数据并对输出进行编码时,您会注意到您收到了垃圾("e?")而不是大便。这将使您相信解码输入文件是错误的。不是。好的。型
问题是,poo被隐式升级为拉丁语1。如果您使用use utf8来制作文本而不是二进制,那么它将再次工作!好的。型
(这是我在帮助Unicode用户时看到的第一个问题。他们做得不好,这破坏了他们的计划。这就是未定义结果的悲哀之处:你可以有一个长期有效的程序,但是当你开始修复它时,它就坏了。别担心,如果你正在向你的程序中添加编码/解码语句,它会中断,这就意味着你有更多的工作要做。下一次,当您从一开始就考虑使用Unicode时,这样做会容易得多!)好的。型
这就是关于Perl和Unicode的全部知识。如果您告诉Perl您的数据是什么,它在所有流行的编程语言中都有最好的Unicode支持。但是,如果你认为它会神奇地知道你在给它输入什么样的文本,那么你将不可避免地丢弃你的数据。仅仅因为您的程序今天在UTF-8终端上工作,并不意味着它明天在UTF-16编码文件上工作。所以现在要确保安全,避免破坏用户数据的麻烦!好的。型
处理Unicode的简单部分是编码输出和解码输入。最困难的部分是找到所有的输入和输出,并确定它是哪种编码。但这就是为什么你能赚大钱的原因:)好的。型好啊。
- 该原理解释得很好,但缺少I/O的实用方法。显式地使用Encode模块既繁琐又容易出错,这使得读取有关I/O的代码非常痛苦。I/O层提供了一种解决方案,因为它们在需要时可以透明地编码和解码。open和binmode允许它们的规范,pragma open设置默认值,正如tchrist在他的回答中建议的那样。
我们一致认为这是一个困难的问题,原因很多,但这正是让每个人都更容易相处的原因。
最近CPAN上有一个模块utf8::all,它试图"打开Unicode"。所有这些。
正如已经指出的,您不能神奇地使整个系统(外部程序、外部Web请求等)也使用Unicode,但我们可以一起工作,使处理常见问题变得更容易的明智工具。这就是我们成为程序员的原因。
如果utf8::all不做您认为应该做的事情,那么让我们改进它以使其更好。或者让我们一起制作其他工具,它们可以同时满足人们的不同需求。
`
- 我看到引用的utf8::all模块有很大的改进空间。它是在unicode_strings特性之前写的,哪个f????????????????L????L?S?修正了regex上有一个/u。我不相信它会引发编码错误的异常,这是您真正必须拥有的。它没有加载到use charnames":full"pragma中,而该pragma尚未自动加载。它不警告[a-z]等,printf串的宽度,用
代替
和.代替\X,但这可能更像是Perl::Critic的问题。如果是我,我会补充??????????????出去了。
- @tchrist utf8的问题跟踪程序::all在这里。github.com/doherty/utf8-all/issues他们很乐意听取您的建议。
- @ Schwern:??????????但是你可以随意从我写的东西中偷取和捏取。老实说,我仍然感觉/学习什么可以做,什么应该做,在哪里做。下面是卸载排序的一个很好的例子:unichars -gs '/(?=\P{Ll})\p{Lower}|(?=\P{Lu})\p{Upper}/x' | ucsort --upper | cat -n | less -r。同样,像... | ucsort --upper --preprocess='s/(\d+)/sprintf"%#012d", $1/ge'这样的小的预处理步骤也非常好,我不想为他们做其他人的决定。我还在构建我的Unicode工具箱。
我认为您误解了Unicode及其与Perl的关系。无论您以何种方式存储数据、Unicode、ISO-8859-1或其他许多东西,您的程序都必须知道如何将它得到的字节解释为输入(解码),以及如何表示它想要输出的信息(编码)。把那个解释搞错了,你就把数据弄混了。在你的程序中没有什么神奇的默认设置可以告诉程序外的东西如何操作。
你认为这很难,很可能,因为你已经习惯了所有的ASCII码。您应该考虑的所有事情都被编程语言和它必须与之交互的所有事情所忽略。如果除了utf-8什么都不用,而你别无选择,那么utf-8也同样简单。但并不是所有东西都使用UTF-8。例如,您不希望输入句柄认为它得到的是UTF-8八位字节,除非它是真的,并且如果从它们读取的内容能够处理UTF-8,您也不希望输出句柄是UTF-8。Perl无法知道这些事情。这就是为什么你是程序员。
我不认为Perl5中的Unicode太复杂。我觉得这很可怕,人们会避开它。有区别。为此,我将Unicode用于学习Perl,第6版,在有效的Perl编程中有很多Unicode的东西。您必须花时间学习和理解Unicode及其工作原理。否则你将无法有效地使用它。
- 我认为你有一个观点:这很可怕。应该是这样吗?对我来说是Unicode的祝福,在Perl5中使用它不是(我不认为任何东西是ASCII,我的母语至少需要ISO8859-4)。我安装了rakudo,我用utf-8(在这个有限的沙盒中)所做的一切都是开箱即用的。我错过什么了吗?我再次强调:拥有微调过的Unicode支持是很好的,但大多数时候并不需要这样做。为了摆脱对这个话题的恐惧,一种方法是每个人都阅读大量的内容来理解其内部。其他:我们有特殊的语用,所以use utf8_everywhere让人快乐。为什么不是最后一个?
- 我仍然认为你没抓住要点。什么工作?你不需要了解内部。您需要了解Externals,以及如何处理具有不同编码和相同字符的不同表示形式的字符串。再读一遍汤姆的建议。他说的大部分话,我打赌你会发现拉库多不适合你。
- 也许你是对的,我错过了重点,我不想争论。[我当然越来越多地阅读汤姆的答案]但兰迪·斯泰纳在他的答案中指出了新的模块utf::all。这个模块有什么问题吗?我们不应该将它(或类似的)与core perl一起使用吗?从我的角度来看,它使得使用UTF-8更加容易,代码也更加清晰。一点也不怕。
- @WK:再读一遍兰迪的答案。他已经告诉过你限制是什么了。
- @布莱恩德福伊:我认为这些限制是好的,就像切里斯特所说的,每个方面都没有魔力子弹(我承认:在问这个问题之前,我没有见过他们中的大多数)。所以,当我们使用诸如utf8::all之类的东西来涵盖许多基本内容时,没有必要每个人都构建自己的大型样板文件,而只需要让utf8处理的基本内容发挥作用。有了"一点也不害怕",我的意思是:每个人都可以开始他的项目,知道基础知识已经被涵盖。是的,你是对的,还有很多问题。但如果开始更容易,我们将有更多的人参与解决这些问题。IMHO
- @wk-"utf8:all"或"uni::perl"唯一的"错误"只是一个-它们不在核心中-所以每个人都必须从CPAN安装它。如果你认为这没什么大不了的——请重新考虑——是的,将utf8与助手模块结合使用会更容易。没有它,核心Perl仍然有Unicode支持——但是非常复杂。这是错误的。
- @JM666:我真的很困惑,你为什么要给我写这个评论?我想要一个像utf8::all这样的核心,但这不取决于我的愿望。我在这里提出的整个主题是一句话:如何使UTF-8处理尽可能简单?所以你的评论是对我整个问题的改写。我不明白,我应该重新考虑什么?
在阅读这篇文章的时候,我经常会觉得人们使用"utf-8"作为"unicode"的同义词。请区分Unicode的"码位"(ASCII码的放大相对码)和Unicode的各种"编码"。其中有一些是目前使用的UTF-8、UTF-16和UTF-32,还有一些是过时的。
请注意,UTF-8(以及所有其他编码)存在,并且仅在输入或输出中有意义。在内部,自Perl5.8.1以来,所有字符串都保持为Unicode"代码点"。是的,您必须启用一些功能,如前所述。
- 我同意人们经常混淆你???????用UTF-8?16?32,但从根本上说,至关重要的是,你说的不是真的吗???????只是一些放大的字符集相对于?S????至多,那不过是简单的?S?10646。U????????包括更多:排序规则、大小写折叠、规范化形式、图形簇、分词和换行、脚本、数字等义符、宽度、双向性、字形变体、上下文行为、区域设置、正则表达式、组合类、100 s属性等等?
- @TChrist:第一步是将数据输入程序并输出到外部世界,而不要破坏它。然后,您可以担心整理、大小写折叠、字形变体等。
- 我同意,让Perl不去垃圾处理输入或输出必须是第一要务。我想要的是有一个模块或pragma,它可以体现以下虚构的对话:"-亲爱的Perl。对于这个程序,所有的输入和输出都将是UTF-8专用的。你能不能不要把我的数据弄乱?-所以只有UFT-8。你确定?-是的。-真的,真的吗?-绝对可以。-你也承认如果我收到非UTF-8数据,我可能会表现得很奇怪?-是的,很好。好吧。
在野外有相当数量的古老代码,其中大部分是以公共CPAN模块的形式存在的。我发现,如果我使用可能受Unicode影响的外部模块,我必须非常小心地启用Unicode,并且仍在尝试在我经常使用的几个Perl脚本中识别和修复一些与Unicode相关的故障(特别是,由于转码问题,ITIVO在任何非7位ASCII的问题上都会严重失败)。
- 定义"启用Unicode"。
- 我的意思是使用-C选项来确保perl与unicode相同,因为我一直让它决定使用iso 8859/1而不是unicode,尽管我明确地设置了$LANG和$LC_ALL。(这可能实际上反映了平台语言环境库中的错误。)不管是什么,我不能在带有重音符号的程序上使用ITIVO是非常恼人的,因为执行该工作的Perl脚本会因转换错误而失效。
- 一个单独的-C没有选项是错误的和容易出错的。你打破了世界。把PERL5OPT设为-C可嫉妒,你就会明白我的意思了。我们在v5.8版就这么做了,这是一场灾难。你不能也不能告诉那些不期望它的程序,现在他们正在处理Unicode,不管他们喜欢与否。还有安全问题。至少,如果传递二进制数据,任何执行print while <>的操作都将中断。所有数据库代码也是如此。这是个糟糕的主意。
- 实际上,我只是泛泛而谈,不是特指没有选择的-C。我一直在使用的特定调用是-CSDA。也就是说,我在5.8.x上呆了很长时间(你好,MacPorts…),所以这可能是其中的一部分。
- 我运行时将perl_Unicode设置为sa。您不能将其设置为d。
- @tchrist:一些perl-varmint已经发布了显示-csda和perl-unicode=sda用法的代码。请利用你在社区中的影响力。必须阻止他!
- @tchrist"一个没有选择的孤单C是错误的,容易出错。"perldoc perlrun对-C的意思很清楚。您是否建议不要使用它,因为它在不同版本的Perl中的行为不同?我试着按照建议设置PERL5OPT,但没有发现有什么不同。
您应该启用unicode字符串功能,如果使用v5.14,这是默认的;
您不应该真正地使用Unicode标识符,尤其是通过UTF8对外部代码使用Unicode标识符,因为它们在Perl5中是不安全的,只有CPerl能够做到这一点。如http://perl11.org/blog/unicode-identifiers.html
关于文件句柄/流的utf8:您需要自己决定外部数据的编码。库不知道这一点,因为甚至libc都不支持utf8,所以很少有合适的utf8数据。还有更多的wtf8,在utf8周围的窗口畸变。
顺便说一句:驼鹿并不是真正的"现代珍珠",他们只是劫持了这个名字。moose是完美的Larry Wall风格的后现代Perl,与bjarne stroustrup风格的任何东西混合在一起,适当的Perl6语法有折衷的偏差,例如使用字符串来表示变量名、糟糕的字段语法,以及一个非常不成熟的简单实现,比适当的实现慢10倍。CPerl和Perl6是真正的现代Perl,其形式遵循函数,实现被简化和优化。